diff --git a/docs/core-properties.html b/docs/core-properties.html index 93f8718..b5577ab 100644 --- a/docs/core-properties.html +++ b/docs/core-properties.html @@ -56,37 +56,37 @@

springdoc.packages-to-scan

*

-

List of Strings.The list of packages to scan (comma separated)

+

List of Strings. The list of packages to scan (comma separated)

springdoc.paths-to-match

/*

-

List of Strings.The list of paths to match (comma separated)

+

List of Strings. The list of paths to match (comma separated)

springdoc.produces-to-match

/*

-

List of Strings.The list of produces mediaTypes to match (comma separated)

+

List of Strings. The list of produces mediaTypes to match (comma separated)

springdoc.headers-to-match

/*

-

List of Strings.The list of headers to match (comma separated)

+

List of Strings. The list of headers to match (comma separated)

springdoc.consumes-to-match

/*

-

List of Strings.The list of consumes mediaTypes to match (comma separated)

+

List of Strings. The list of consumes mediaTypes to match (comma separated)

springdoc.paths-to-exclude

-

List of Strings.The list of paths to exclude (comma separated)

+

List of Strings. The list of paths to exclude (comma separated)

springdoc.packages-to-exclude

-

List of Strings.The list of packages to exclude (comma separated)

+

List of Strings. The list of packages to exclude (comma separated)

springdoc.default-consumes-media-type

@@ -96,7 +96,7 @@

springdoc.default-produces-media-type

/

-

String.The default produces media type.

+

String. The default produces media type.

springdoc.cache.disabled

@@ -124,59 +124,54 @@

Boolean. When true, automatically adds @ControllerAdvice responses to all the generated responses.

-

springdoc.api-docs.groups.enabled

-

true

-

Boolean. To disable the springdoc-openapi groups.

- -

springdoc.group-configs[0].group

-

String.The group name

+

String. The group name

springdoc.group-configs[0].display-name

-

String.The display name of the group.

+

String. The display name of the group.

springdoc.group-configs[0].packages-to-scan

*

-

List of Strings.The list of packages to scan for a group (comma separated)

+

List of Strings. The list of packages to scan for a group (comma separated)

springdoc.group-configs[0].paths-to-match

/*

-

List of Strings.The list of paths to match for a group(comma separated)

+

List of Strings. The list of paths to match for a group (comma separated)

springdoc.group-configs[0].paths-to-exclude

``

-

List of Strings.The list of paths to exclude for a group(comma separated)

+

List of Strings. The list of paths to exclude for a group (comma separated)

springdoc.group-configs[0].packages-to-exclude

-

List of Strings.The list of packages to exclude for a group(comma separated)

+

List of Strings. The list of packages to exclude for a group (comma separated)

springdoc.group-configs[0].produces-to-match

/*

-

List of Strings.The list of produces mediaTypes to match (comma separated)

+

List of Strings. The list of produces mediaTypes to match (comma separated)

springdoc.group-configs[0].consumes-to-match

/*

-

List of Strings.The list of consumes mediaTypes to match (comma separated)

+

List of Strings. The list of consumes mediaTypes to match (comma separated)

springdoc.group-configs[0].headers-to-match

/*

-

List of Strings.The list of headers to match (comma separated)

+

List of Strings. The list of headers to match (comma separated)

springdoc.webjars.prefix

/webjars

-

String, To change the webjars prefix that is visible the URL of swagger-ui for spring-webflux.

+

String. To change the webjars prefix that is visible the URL of swagger-ui for spring-webflux.

springdoc.api-docs.resolve-schema-properties

@@ -224,14 +219,9 @@

Boolean. To make spring security login-endpoint visible.

-

springdoc.pre-loading-enabled

-

false

-

Boolean. Pre-loading setting to load OpenAPI on application startup.

- -

springdoc.pre-loading-locales

-

List of Strings.The list of locales to load OpenAPI on application startup.(comma separated) If not specified, it will preload with the default Locale.

+

List of Strings. The list of locales to load OpenAPI on application startup (comma separated). If not specified, it will preload with the default Locale.

springdoc.writer-with-order-by-keys

@@ -266,7 +256,7 @@

springdoc.enable-kotlin

true

-

Boolproperty resolver on @Schema (extensionean. To enable Kotlin support.

+

Boolean. To enable Kotlin support.

springdoc.enable-hateoas

@@ -280,8 +270,8 @@

springdoc.api-docs.version

-

openapi_3_0

-

String. To Choose OpenAPI 3.0 or OpenAPI 3.1 (using the value OPENAPI_3_1).

+

openapi_3_1

+

String. To choose OpenAPI 3.0 or OpenAPI 3.1 (using the value OPENAPI_3_1).

springdoc.default-flat-param-object

@@ -318,24 +308,32 @@

false

Boolean. Adjust indentation when parsing the @Operation annotation in Kotlin.

+ +

springdoc.allowed-locales

+ +

List of Strings. The list of allowed locales for OpenAPI (comma separated, for example US,fr-CA).

+ + +

springdoc.enable-extra-schemas

+

true

+

Boolean. To enable default support for extra Schemas, from java.time package like LocalTime, Duration, but also other Java classes like java.util.Locale or java.nio.charset.Charset

+ + +

springdoc.explicit-object-schema

+

false

+

Boolean. Set explicit-object-schema to true to always include type: object in the schema, or to false to omit type: object.

+ + +

springdoc.use-arbitrary-schemas

+

false

+

Boolean. When set to true, schemas without a defined type will be deserialized as an ArbitrarySchema (with no type), instead of an ObjectSchema with type: object.

+ - - - - diff --git a/docs/demos.html b/docs/demos.html index 1dc997f..b1248aa 100644 --- a/docs/demos.html +++ b/docs/demos.html @@ -40,6 +40,9 @@

Demo Spring Boot 3 Web MVC with OpenAPI 3

  • +

    Demo Spring Boot 3 WebFlux with OpenAPI 3

    +
  • +
  • Demo Spring Boot 3 WebFlux with Functional endpoints OpenAPI 3

  • @@ -71,25 +74,24 @@

    - - - + + + diff --git a/docs/faq.html b/docs/faq.html index fbfb439..042567c 100644 --- a/docs/faq.html +++ b/docs/faq.html @@ -230,7 +230,7 @@

    -
    springdoc.swagger-ui.supportedSubmitMethods="get", "put", "post", "delete", "options", "head", "patch", "trace"
    +
    springdoc.swagger-ui.supportedSubmitMethods=get, put, post, delete, options, head, patch, trace
    @@ -298,15 +298,13 @@

    -
    ---
    -@Bean
    +
    @Bean
     @Primary
     fun swaggerUiConfig(config: SwaggerUiConfigProperties): SwaggerUiConfigProperties {
         config.showCommonExtensions = true
         config.queryConfigEnabled = true
         return config
     }
    ----
     
    @@ -579,7 +577,7 @@

    +
    +
      +
    • +

      If you need to manually adjust the URL displayed in the Swagger UI, implement the ServerBaseUrlCustomizer interface. This might be necessary to remove the port number, for example.

      +
    • +
    +
    +
    +
    +
    @Bean
    +public class CustomServerBaseUrlCustomizer implements ServerBaseUrlCustomizer {
    +    @Override
    +    public String customize(String serverBaseUrl) {
    +        try {
    +            URL url = new URL(serverBaseUrl);
    +            if (url.getHost().contains(".com")) {
    +                serverBaseUrl = new URL(url.getProtocol(),url.getHost(),url.getFile()).toString();
    +            }
    +        } catch (MalformedURLException ex) {
    +            // nothing we can do
    +        }
    +
    +        return serverBaseUrl;
    +    }
    +}
    +
    +
    +
    @@ -662,7 +688,7 @@

    @@ -1241,8 +1267,40 @@

    +
    +
    import io.swagger.v3.oas.annotations.Parameter;
    +import io.swagger.v3.oas.annotations.media.Content;
    +import io.swagger.v3.oas.annotations.media.Encoding;
    +import io.swagger.v3.oas.annotations.parameters.RequestBody;
    +
    +@PostMapping(value = "/upload", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
    +public ResponseEntity<?> upload(@Parameter(description = "file") final MultipartFile file) {
    +    return null;
    +}
    +
    +@PostMapping(value = "/uploadFileWithQuery", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
    +public ResponseEntity<?> uploadFileWithQuery(@Parameter(description = "file") @RequestPart("file") final MultipartFile file,
    +        @Parameter(description = "An extra query parameter") @RequestParam String name) {
    +    return null;
    +}
    +
    +@PostMapping(value = "/uploadFileWithJson", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}, produces = {
    +        MediaType.APPLICATION_JSON_VALUE})
    +public ResponseEntity<?> uploadFileWithJson(
    +        @RequestBody(content = @Content(encoding = @Encoding(name = "jsonRequest", contentType = MediaType.APPLICATION_JSON_VALUE)))
    +        @Parameter(description = "An extra JSON payload sent with file") @RequestPart("jsonRequest") final JsonRequest jsonRequest,
    +        @RequestPart("file") final MultipartFile file) {
    +    return null;
    +}
    +
    +
    +

    Can I use @Parameter inside @Operation annotation?

    @@ -1317,11 +1375,6 @@

    @@ -1453,20 +1506,25 @@

    For testing purposes only, you can test temporarily using the last springdoc-openapi SNAPSHOT

  • -

    To achieve that, you can on your pom.xml or your settings.xml the following section:

    +

    To achieve that, configure your pom.xml file with the following <repositories> section:

  • -
         <repositories>
    -       <repository>
    -         <id>snapshots-repo</id>
    -         <url>https://s01.oss.sonatype.org/content/repositories/snapshots</url>
    -         <releases><enabled>false</enabled></releases>
    -         <snapshots><enabled>true</enabled></snapshots>
    -       </repository>
    -     </repositories>
    +
        <repositories>
    +      <repository>
    +        <name>Central Portal Snapshots</name>
    +        <id>central-portal-snapshots</id>
    +        <url>https://central.sonatype.com/repository/maven-snapshots/</url>
    +        <releases>
    +          <enabled>false</enabled>
    +        </releases>
    +        <snapshots>
    +          <enabled>true</enabled>
    +        </snapshots>
    +      </repository>
    +    </repositories>
    @@ -1537,7 +1595,7 @@

    @@ -1844,12 +1902,115 @@

    <
    +

    How to Integrate Open API 3 with Spring project (not Spring Boot)?

    +
    +

    When your application is using spring without (spring-boot), you need to add beans and auto-configuration that are natively provided in spring-boot.

    +
    +
    +

    For example, lets assume you want load the swagger-ui in spring-mvc application:

    +
    +
    +
      +
    • +

      You mainly, need to add the springdoc-openapi module

      +
    • +
    +
    +
    +
    +
    <dependency>
    +   <groupId>org.springdoc</groupId>
    +   <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
    +   <version>last.version</version>
    +</dependency>
    +
    +
    +
    +
      +
    • +

      If you don’t have the spring-boot and spring-boot-autoconfigure dependencies, you need to add them. And pay attention to the compatibility matrix, between you spring.version and spring-boot.version. For example, in this case (spring.version=5.1.12.RELEASE):

      +
    • +
    +
    +
    +
    +
    		<dependency>
    +			<groupId>org.springframework.boot</groupId>
    +			<artifactId>spring-boot-autoconfigure</artifactId>
    +			<version>3.3.3</version>
    +		</dependency>
    +
    +
    +
    +
      +
    • +

      Scan for the springdoc-openapi 'auto-configuration classes that spring-boot automatically loads for you.

      +
    • +
    • +

      Depending on your module, you can find them on the file: spring.factories of each springdoc-openapi module.

      +
    • +
    +
    +
    +
    +
    @Configuration
    +@EnableWebMvc
    +public class WebConfig implements WebApplicationInitializer {
    +
    +	@Override
    +	public void onStartup(ServletContext servletContext)  {
    +		WebApplicationContext context = getContext();
    +		servletContext.addListener(new ContextLoaderListener(context));
    +		ServletRegistration.Dynamic dispatcher = servletContext.addServlet("RestServlet",
    +				new DispatcherServlet(context));
    +		dispatcher.setLoadOnStartup(1);
    +		dispatcher.addMapping("/*");
    +	}
    +
    +	private AnnotationConfigWebApplicationContext getContext() {
    +		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
    +		context.register(this.getClass(),
    +				SpringDocConfiguration.class,
    +				SpringDocConfigProperties.class,
    +				SpringDocSpecPropertiesConfiguration.class,
    +				SpringDocWebMvcConfiguration.class,
    +				MultipleOpenApiSupportConfiguration.class,
    +				SwaggerConfig.class,
    +				SwaggerUiConfigProperties.class,
    +				SwaggerUiOAuthProperties.class,
    +		);
    +		return context;
    +	}
    +}
    +
    +
    +
    +
    +
      +
    • +

      Depending on your module, you can find them on the file: org.springframework.boot.autoconfigure.AutoConfiguration.imports of each springdoc-openapi module.

      +
    • +
    • +

      For groups usage make sure your GroupedOpenApi Beans are scanned.

      +
    • +
    • +

      If additionally, you are using custom context path: /my-servlet-path. Make sure you declare the following property:

      +
    • +
    +
    +
    +
    +
    spring.mvc.servlet.path=/my-servlet-path
    +
    +
    +
    +

    What is the compatibility matrix of springdoc-openapi with spring-boot ?

    springdoc-openapi 2.x is compatible with spring-boot 3.

    -

    In general, you should only pick the last stable version as per today 2.6.0.

    +

    In general, you should only pick the last stable version as per today 2.8.11.

    More precisely, this the exhaustive list of spring-boot versions against which springdoc-openapi has been built:

    @@ -1859,16 +2020,34 @@

    - + -spring-boot Versions -Minimum springdoc-openapi Versions +

    Spring Boot Versions

    +

    Springdoc OpenAPI Versions

    + + +

    3.5.x

    +

    2.8.x

    + + +

    3.4.x

    +

    2.7.x - 2.8.x

    + + +

    3.3.x

    +

    2.6.x

    + + +

    3.2.x

    +

    2.3.x - 2.5.x

    + + +

    3.1.x

    +

    2.2.x

    - -

    3.0.x

    -

    2.0.x+

    +

    2.0.x - 2.1.x

    2.7.x, 1.5.x

    @@ -1944,25 +2123,13 @@

    - - - - diff --git a/docs/favicon.ico b/docs/favicon.ico index 0dfbcd7..45468e6 100644 Binary files a/docs/favicon.ico and b/docs/favicon.ico differ diff --git a/docs/features.html b/docs/features.html index d648c6f..dfa5983 100644 --- a/docs/features.html +++ b/docs/features.html @@ -143,19 +143,19 @@

    @@ -165,7 +165,7 @@

    @@ -302,7 +302,7 @@

    @@ -312,7 +312,7 @@

    @@ -335,25 +335,24 @@

    - - - + + + diff --git a/docs/getting-started.html b/docs/getting-started.html index 42da390..4c026c6 100644 --- a/docs/getting-started.html +++ b/docs/getting-started.html @@ -40,7 +40,7 @@

    Getting S
       <dependency>
           <groupId>org.springdoc</groupId>
           <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
    -      <version>2.6.0</version>
    +      <version>2.8.11</version>
        </dependency>
    @@ -69,7 +69,7 @@

    Getting S
  • -

    Documentation can be available in yaml format as well, on the following path : /v3/api-docs.yaml

    +

    Documentation will be available in yaml format as well, on the following path : /v3/api-docs.yaml

  • @@ -91,24 +91,23 @@

    Getting S springdoc.swagger-ui.path=/swagger-ui.html - - - - + + + diff --git a/docs/img/LVM_Versicherung_2010_logo.svg.png b/docs/img/LVM_Versicherung_2010_logo.svg.png new file mode 100644 index 0000000..5aac7e9 Binary files /dev/null and b/docs/img/LVM_Versicherung_2010_logo.svg.png differ diff --git a/docs/img/gdnext.png b/docs/img/gdnext.png new file mode 100644 index 0000000..1523834 Binary files /dev/null and b/docs/img/gdnext.png differ diff --git a/docs/img/jetbrains.svg b/docs/img/jetbrains.svg index 75d4d21..cb3a2a0 100644 --- a/docs/img/jetbrains.svg +++ b/docs/img/jetbrains.svg @@ -1,66 +1,13 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/docs/img/springdoc/springdoc-favicon.svg b/docs/img/springdoc/springdoc-favicon.svg new file mode 100644 index 0000000..21eeef6 --- /dev/null +++ b/docs/img/springdoc/springdoc-favicon.svg @@ -0,0 +1,166 @@ + + + + Created with Fabric.js 4.6.0 diff --git a/docs/img/springdoc/springdoc-logo.svg b/docs/img/springdoc/springdoc-logo.svg new file mode 100644 index 0000000..f3f7bb8 --- /dev/null +++ b/docs/img/springdoc/springdoc-logo.svg @@ -0,0 +1,139 @@ + + + + Created with Fabric.js 4.6.0 diff --git a/docs/index.html b/docs/index.html index c098eda..767ebcb 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,31 +1,41 @@ - - - - - - OpenAPI 3 Library for spring-boot - - OpenAPI 3 Library for spring-boot - - - - - - - - - - springdoc-openapi v2.5.0 - - - + + + + + +OpenAPI 3 Library for spring-boot + +OpenAPI 3 Library for spring-boot + + + + + + + + + +springdoc-openapi v2.8.11 + + + + + + +
  • -

    Documentation can be available in yaml format as well, on the following path : /v3/api-docs.yaml

    +

    Documentation will be available in yaml format as well, on the following path : /v3/api-docs.yaml

  • @@ -358,18 +367,17 @@

    2. Gettin springdoc.swagger-ui.path=/swagger-ui.html - - - - + + + @@ -456,7 +464,7 @@

    - - - - @@ -2012,6 +2014,9 @@

    Demo Spring Boot 3 Web MVC with OpenAPI 3

  • +

    Demo Spring Boot 3 WebFlux with OpenAPI 3

    +
  • +
  • Demo Spring Boot 3 WebFlux with Functional endpoints OpenAPI 3

  • @@ -2043,18 +2048,17 @@

    - - - + + + @@ -2246,18 +2250,6 @@

    - - - @@ -2302,7 +2294,7 @@

    - - - @@ -2510,22 +2490,10 @@

    - - - - @@ -2554,6 +2522,12 @@

    + + + + + +

    11.1. Benefits of being a bronze sponsor

    @@ -2611,18 +2585,6 @@

    - - -

    @@ -2641,21 +2603,9 @@

    12. Special Thanks

    -JetBrains +JetBrains logo
    - - - - @@ -2927,15 +2877,13 @@

    -
    ---
    -@Bean
    +
    @Bean
     @Primary
     fun swaggerUiConfig(config: SwaggerUiConfigProperties): SwaggerUiConfigProperties {
         config.showCommonExtensions = true
         config.queryConfigEnabled = true
         return config
     }
    ----
     
    @@ -3208,7 +3156,7 @@

    +
    +
      +
    • +

      If you need to manually adjust the URL displayed in the Swagger UI, implement the ServerBaseUrlCustomizer interface. This might be necessary to remove the port number, for example.

      +
    • +
    +
    +
    +
    +
    @Bean
    +public class CustomServerBaseUrlCustomizer implements ServerBaseUrlCustomizer {
    +    @Override
    +    public String customize(String serverBaseUrl) {
    +        try {
    +            URL url = new URL(serverBaseUrl);
    +            if (url.getHost().contains(".com")) {
    +                serverBaseUrl = new URL(url.getProtocol(),url.getHost(),url.getFile()).toString();
    +            }
    +        } catch (MalformedURLException ex) {
    +            // nothing we can do
    +        }
    +
    +        return serverBaseUrl;
    +    }
    +}
    +
    +
    +
    @@ -3291,7 +3267,7 @@

    @@ -3870,8 +3846,40 @@

    +
    +
    import io.swagger.v3.oas.annotations.Parameter;
    +import io.swagger.v3.oas.annotations.media.Content;
    +import io.swagger.v3.oas.annotations.media.Encoding;
    +import io.swagger.v3.oas.annotations.parameters.RequestBody;
    +
    +@PostMapping(value = "/upload", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
    +public ResponseEntity<?> upload(@Parameter(description = "file") final MultipartFile file) {
    +    return null;
    +}
    +
    +@PostMapping(value = "/uploadFileWithQuery", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
    +public ResponseEntity<?> uploadFileWithQuery(@Parameter(description = "file") @RequestPart("file") final MultipartFile file,
    +        @Parameter(description = "An extra query parameter") @RequestParam String name) {
    +    return null;
    +}
    +
    +@PostMapping(value = "/uploadFileWithJson", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}, produces = {
    +        MediaType.APPLICATION_JSON_VALUE})
    +public ResponseEntity<?> uploadFileWithJson(
    +        @RequestBody(content = @Content(encoding = @Encoding(name = "jsonRequest", contentType = MediaType.APPLICATION_JSON_VALUE)))
    +        @Parameter(description = "An extra JSON payload sent with file") @RequestPart("jsonRequest") final JsonRequest jsonRequest,
    +        @RequestPart("file") final MultipartFile file) {
    +    return null;
    +}
    +
    +
    +

    13.54. Can I use @Parameter inside @Operation annotation?

    @@ -3946,11 +3954,6 @@

    @@ -4082,20 +4085,25 @@

    For testing purposes only, you can test temporarily using the last springdoc-openapi SNAPSHOT

  • -

    To achieve that, you can on your pom.xml or your settings.xml the following section:

    +

    To achieve that, configure your pom.xml file with the following <repositories> section:

  • -
         <repositories>
    -       <repository>
    -         <id>snapshots-repo</id>
    -         <url>https://s01.oss.sonatype.org/content/repositories/snapshots</url>
    -         <releases><enabled>false</enabled></releases>
    -         <snapshots><enabled>true</enabled></snapshots>
    -       </repository>
    -     </repositories>
    +
        <repositories>
    +      <repository>
    +        <name>Central Portal Snapshots</name>
    +        <id>central-portal-snapshots</id>
    +        <url>https://central.sonatype.com/repository/maven-snapshots/</url>
    +        <releases>
    +          <enabled>false</enabled>
    +        </releases>
    +        <snapshots>
    +          <enabled>true</enabled>
    +        </snapshots>
    +      </repository>
    +    </repositories>
    @@ -4166,7 +4174,7 @@

    @@ -4473,12 +4481,115 @@

    -

    13.78. What is the compatibility matrix of springdoc-openapi with spring-boot ?

    +

    13.78. How to Integrate Open API 3 with Spring project (not Spring Boot)?

    +
    +

    When your application is using spring without (spring-boot), you need to add beans and auto-configuration that are natively provided in spring-boot.

    +
    +
    +

    For example, lets assume you want load the swagger-ui in spring-mvc application:

    +
    +
    +
      +
    • +

      You mainly, need to add the springdoc-openapi module

      +
    • +
    +
    +
    +
    +
    <dependency>
    +   <groupId>org.springdoc</groupId>
    +   <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
    +   <version>last.version</version>
    +</dependency>
    +
    +
    +
    +
      +
    • +

      If you don’t have the spring-boot and spring-boot-autoconfigure dependencies, you need to add them. And pay attention to the compatibility matrix, between you spring.version and spring-boot.version. For example, in this case (spring.version=5.1.12.RELEASE):

      +
    • +
    +
    +
    +
    +
            <dependency>
    +            <groupId>org.springframework.boot</groupId>
    +            <artifactId>spring-boot-autoconfigure</artifactId>
    +            <version>3.3.3</version>
    +        </dependency>
    +
    +
    +
    +
      +
    • +

      Scan for the springdoc-openapi 'auto-configuration classes that spring-boot automatically loads for you.

      +
    • +
    • +

      Depending on your module, you can find them on the file: spring.factories of each springdoc-openapi module.

      +
    • +
    +
    +
    +
    +
    @Configuration
    +@EnableWebMvc
    +public class WebConfig implements WebApplicationInitializer {
    +
    +    @Override
    +    public void onStartup(ServletContext servletContext)  {
    +        WebApplicationContext context = getContext();
    +        servletContext.addListener(new ContextLoaderListener(context));
    +        ServletRegistration.Dynamic dispatcher = servletContext.addServlet("RestServlet",
    +                new DispatcherServlet(context));
    +        dispatcher.setLoadOnStartup(1);
    +        dispatcher.addMapping("/*");
    +    }
    +
    +    private AnnotationConfigWebApplicationContext getContext() {
    +        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
    +        context.register(this.getClass(),
    +                SpringDocConfiguration.class,
    +                SpringDocConfigProperties.class,
    +                SpringDocSpecPropertiesConfiguration.class,
    +                SpringDocWebMvcConfiguration.class,
    +                MultipleOpenApiSupportConfiguration.class,
    +                SwaggerConfig.class,
    +                SwaggerUiConfigProperties.class,
    +                SwaggerUiOAuthProperties.class,
    +        );
    +        return context;
    +    }
    +}
    +
    +
    +
    +
    +
      +
    • +

      Depending on your module, you can find them on the file: org.springframework.boot.autoconfigure.AutoConfiguration.imports of each springdoc-openapi module.

      +
    • +
    • +

      For groups usage make sure your GroupedOpenApi Beans are scanned.

      +
    • +
    • +

      If additionally, you are using custom context path: /my-servlet-path. Make sure you declare the following property:

      +
    • +
    +
    +
    +
    +
    spring.mvc.servlet.path=/my-servlet-path
    +
    +
    +
    +
    +

    13.79. What is the compatibility matrix of springdoc-openapi with spring-boot ?

    springdoc-openapi 2.x is compatible with spring-boot 3.

    -

    In general, you should only pick the last stable version as per today 2.6.0.

    +

    In general, you should only pick the last stable version as per today 2.8.11.

    More precisely, this the exhaustive list of spring-boot versions against which springdoc-openapi has been built:

    @@ -4488,16 +4599,34 @@

    - + -spring-boot Versions -Minimum springdoc-openapi Versions +

    Spring Boot Versions

    +

    Springdoc OpenAPI Versions

    + + +

    3.5.x

    +

    2.8.x

    + + +

    3.4.x

    +

    2.7.x - 2.8.x

    + + +

    3.3.x

    +

    2.6.x

    + + +

    3.2.x

    +

    2.3.x - 2.5.x

    + + +

    3.1.x

    +

    2.2.x

    - -

    3.0.x

    -

    2.0.x+

    +

    2.0.x - 2.1.x

    2.7.x, 1.5.x

    @@ -4531,7 +4660,7 @@

    -

    13.79. Why am i getting an error: Swagger UI unable to render definition, when overriding the default spring registered HttpMessageConverter?

    +

    13.80. Why am i getting an error: Swagger UI unable to render definition, when overriding the default spring registered HttpMessageConverter?

    When overriding the default spring-boot registered HttpMessageConverter, you should have ByteArrayHttpMessageConverter registered as well to have proper springdoc-openapi support.

    @@ -4556,7 +4685,7 @@

    -

    13.80. Some parameters are not generated in the resulting OpenAPI spec.

    +

    13.81. Some parameters are not generated in the resulting OpenAPI spec.

    The issue is caused by the changes introduced by Spring-Boot 3.2.0 in particular for the Parameter Name Discovery. @@ -4573,65 +4702,15 @@

    - - - -
    - - - - - - - - - diff --git a/docs/intro.html b/docs/intro.html index 7c7c0c7..9181077 100644 --- a/docs/intro.html +++ b/docs/intro.html @@ -76,24 +76,12 @@

    Introduction

    This is a community-based project, not maintained by the Spring Framework Contributors (Pivotal).

    - - - - diff --git a/docs/migrating-from-springdoc-v1.html b/docs/migrating-from-springdoc-v1.html index 3cb50b0..22e713c 100644 --- a/docs/migrating-from-springdoc-v1.html +++ b/docs/migrating-from-springdoc-v1.html @@ -217,24 +217,12 @@

    - - - diff --git a/docs/migrating-from-springfox.html b/docs/migrating-from-springfox.html index f954f48..ec21316 100644 --- a/docs/migrating-from-springfox.html +++ b/docs/migrating-from-springfox.html @@ -44,7 +44,7 @@

    <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> - <version>2.6.0</version> + <version>2.8.11</version> </dependency> @@ -71,7 +71,7 @@

    - - - diff --git a/docs/modules.html b/docs/modules.html index 1b30e98..d560fc4 100644 --- a/docs/modules.html +++ b/docs/modules.html @@ -73,7 +73,7 @@

    <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-starter-webmvc-api</artifactId> - <version>2.6.0</version> + <version>2.8.11</version> </dependency> @@ -113,7 +113,7 @@

    - - - - diff --git a/docs/properties.html b/docs/properties.html index f2e6972..8389073 100644 --- a/docs/properties.html +++ b/docs/properties.html @@ -33,7 +33,7 @@

    Springdoc-openapi Properties

    -

    springdoc-openapi relies on standard spring configuration properties (yml or properties) using the standard files locations.

    +

    springdoc-openapi relies on standard spring configuration properties (yml or properties) using the standard files locations.

    springdoc-openapi core properties

    @@ -64,37 +64,37 @@

    springdoc.packages-to-scan

    *

    -

    List of Strings.The list of packages to scan (comma separated)

    +

    List of Strings. The list of packages to scan (comma separated)

    springdoc.paths-to-match

    /*

    -

    List of Strings.The list of paths to match (comma separated)

    +

    List of Strings. The list of paths to match (comma separated)

    springdoc.produces-to-match

    /*

    -

    List of Strings.The list of produces mediaTypes to match (comma separated)

    +

    List of Strings. The list of produces mediaTypes to match (comma separated)

    springdoc.headers-to-match

    /*

    -

    List of Strings.The list of headers to match (comma separated)

    +

    List of Strings. The list of headers to match (comma separated)

    springdoc.consumes-to-match

    /*

    -

    List of Strings.The list of consumes mediaTypes to match (comma separated)

    +

    List of Strings. The list of consumes mediaTypes to match (comma separated)

    springdoc.paths-to-exclude

    -

    List of Strings.The list of paths to exclude (comma separated)

    +

    List of Strings. The list of paths to exclude (comma separated)

    springdoc.packages-to-exclude

    -

    List of Strings.The list of packages to exclude (comma separated)

    +

    List of Strings. The list of packages to exclude (comma separated)

    springdoc.default-consumes-media-type

    @@ -104,7 +104,7 @@

    springdoc.default-produces-media-type

    /

    -

    String.The default produces media type.

    +

    String. The default produces media type.

    springdoc.cache.disabled

    @@ -132,59 +132,54 @@

    Boolean. When true, automatically adds @ControllerAdvice responses to all the generated responses.

    -

    springdoc.api-docs.groups.enabled

    -

    true

    -

    Boolean. To disable the springdoc-openapi groups.

    - -

    springdoc.group-configs[0].group

    -

    String.The group name

    +

    String. The group name

    springdoc.group-configs[0].display-name

    -

    String.The display name of the group.

    +

    String. The display name of the group.

    springdoc.group-configs[0].packages-to-scan

    *

    -

    List of Strings.The list of packages to scan for a group (comma separated)

    +

    List of Strings. The list of packages to scan for a group (comma separated)

    springdoc.group-configs[0].paths-to-match

    /*

    -

    List of Strings.The list of paths to match for a group(comma separated)

    +

    List of Strings. The list of paths to match for a group (comma separated)

    springdoc.group-configs[0].paths-to-exclude

    ``

    -

    List of Strings.The list of paths to exclude for a group(comma separated)

    +

    List of Strings. The list of paths to exclude for a group (comma separated)

    springdoc.group-configs[0].packages-to-exclude

    -

    List of Strings.The list of packages to exclude for a group(comma separated)

    +

    List of Strings. The list of packages to exclude for a group (comma separated)

    springdoc.group-configs[0].produces-to-match

    /*

    -

    List of Strings.The list of produces mediaTypes to match (comma separated)

    +

    List of Strings. The list of produces mediaTypes to match (comma separated)

    springdoc.group-configs[0].consumes-to-match

    /*

    -

    List of Strings.The list of consumes mediaTypes to match (comma separated)

    +

    List of Strings. The list of consumes mediaTypes to match (comma separated)

    springdoc.group-configs[0].headers-to-match

    /*

    -

    List of Strings.The list of headers to match (comma separated)

    +

    List of Strings. The list of headers to match (comma separated)

    springdoc.webjars.prefix

    /webjars

    -

    String, To change the webjars prefix that is visible the URL of swagger-ui for spring-webflux.

    +

    String. To change the webjars prefix that is visible the URL of swagger-ui for spring-webflux.

    springdoc.api-docs.resolve-schema-properties

    @@ -232,14 +227,9 @@

    Boolean. To make spring security login-endpoint visible.

    -

    springdoc.pre-loading-enabled

    -

    false

    -

    Boolean. Pre-loading setting to load OpenAPI on application startup.

    - -

    springdoc.pre-loading-locales

    -

    List of Strings.The list of locales to load OpenAPI on application startup.(comma separated) If not specified, it will preload with the default Locale.

    +

    List of Strings. The list of locales to load OpenAPI on application startup (comma separated). If not specified, it will preload with the default Locale.

    springdoc.writer-with-order-by-keys

    @@ -274,7 +264,7 @@

    springdoc.enable-kotlin

    true

    -

    Boolproperty resolver on @Schema (extensionean. To enable Kotlin support.

    +

    Boolean. To enable Kotlin support.

    springdoc.enable-hateoas

    @@ -288,8 +278,8 @@

    springdoc.api-docs.version

    -

    openapi_3_0

    -

    String. To Choose OpenAPI 3.0 or OpenAPI 3.1 (using the value OPENAPI_3_1).

    +

    openapi_3_1

    +

    String. To choose OpenAPI 3.0 or OpenAPI 3.1 (using the value OPENAPI_3_1).

    springdoc.default-flat-param-object

    @@ -326,20 +316,28 @@

    false

    Boolean. Adjust indentation when parsing the @Operation annotation in Kotlin.

    + +

    springdoc.allowed-locales

    + +

    List of Strings. The list of allowed locales for OpenAPI (comma separated, for example US,fr-CA).

    + + +

    springdoc.enable-extra-schemas

    +

    true

    +

    Boolean. To enable default support for extra Schemas, from java.time package like LocalTime, Duration, but also other Java classes like java.util.Locale or java.nio.charset.Charset

    + + +

    springdoc.explicit-object-schema

    +

    false

    +

    Boolean. Set explicit-object-schema to true to always include type: object in the schema, or to false to omit type: object.

    + + +

    springdoc.use-arbitrary-schemas

    +

    false

    +

    Boolean. When set to true, schemas without a defined type will be deserialized as an ArbitrarySchema (with no type), instead of an ObjectSchema with type: object.

    + - - - -

    diff --git a/docs/sponsor.html b/docs/sponsor.html index f473a4a..f59c8ab 100644 --- a/docs/sponsor.html +++ b/docs/sponsor.html @@ -54,6 +54,12 @@ + + + + + +

    Benefits of being a bronze sponsor

    @@ -111,25 +117,13 @@

    - - -

    diff --git a/docs/thanks.html b/docs/thanks.html index ee574ee..bc4a061 100644 --- a/docs/thanks.html +++ b/docs/thanks.html @@ -44,27 +44,15 @@

    Special Thanks

    -JetBrains +JetBrains logo
    - - - - diff --git a/docs/ui-properties.html b/docs/ui-properties.html index 2cf9876..d7e5761 100644 --- a/docs/ui-properties.html +++ b/docs/ui-properties.html @@ -65,8 +65,8 @@

    springdoc.swagger-ui.validatorUrl

    -

    https://validator.swagger.io/validator

    -

    By default, Swagger UI attempts to validate specs against swagger.io’s online validator. You can use this parameter to set a different validator URL, for example for locally deployed validators Validator Badge. Setting it to either none, 127.0.0.1 or localhost will disable validation.

    + +

    By default, Swagger UI does not validate specs. You can use this parameter to set a validator URL, for example for against swagger.io’s online validator.

    springdoc.swagger-ui.tryItOutEnabled

    @@ -151,7 +151,7 @@

    springdoc.swagger-ui.supportedSubmitMethods

    -

    Array=["get", "put", "post", "delete", "options", "head", "patch", "trace"]. List of HTTP methods that have the "Try it out" feature enabled. An empty array disables "Try it out" for all operations. This does not filter the operations from the display.

    +

    Array=[get, put, post, delete, options, head, patch, trace]. List of HTTP methods that have the "Try it out" feature enabled. An empty array disables "Try it out" for all operations. This does not filter the operations from the display.

    springdoc.swagger-ui.queryConfigEnabled

    @@ -265,22 +265,21 @@ - - - - + + + diff --git a/docs/v1/core-properties.html b/docs/v1/core-properties.html index b46434b..a51d985 100644 --- a/docs/v1/core-properties.html +++ b/docs/v1/core-properties.html @@ -124,11 +124,6 @@

    Boolean. When true, automatically adds @ControllerAdvice responses to all the generated responses.

    -

    springdoc.api-docs.groups.enabled

    -

    true

    -

    Boolean. To disable the springdoc-openapi groups.

    - -

    springdoc.group-configs[0].group

    String.The group name

    @@ -295,22 +290,10 @@ - - - - diff --git a/docs/v1/demos.html b/docs/v1/demos.html index f435940..0eca07f 100644 --- a/docs/v1/demos.html +++ b/docs/v1/demos.html @@ -77,25 +77,13 @@

    - - - diff --git a/docs/v1/faq.html b/docs/v1/faq.html index 5fc3063..49bfed8 100644 --- a/docs/v1/faq.html +++ b/docs/v1/faq.html @@ -230,7 +230,7 @@

    -
    springdoc.swagger-ui.supportedSubmitMethods="get", "put", "post", "delete", "options", "head", "patch", "trace"
    +
    springdoc.swagger-ui.supportedSubmitMethods=get, put, post, delete, options, head, patch, trace
    @@ -298,15 +298,13 @@

    -
    ---
    -@Bean
    +
    @Bean
     @Primary
     fun swaggerUiConfig(config: SwaggerUiConfigProperties): SwaggerUiConfigProperties {
         config.showCommonExtensions = true
         config.queryConfigEnabled = true
         return config
     }
    ----
     
    @@ -655,7 +653,7 @@

    @@ -665,9 +663,9 @@

    @Bean
    -public OpenApiCustomiser consumerTypeHeaderOpenAPICustomiser() {
    -return openApi -> openApi.getPaths().values().stream().flatMap(pathItem -> pathItem.readOperations().stream())
    -    .forEach(operation -> operation.addParametersItem(new HeaderParameter().$ref("#/components/parameters/myConsumerTypeHeader")));
    +public OpenApiCustomizer customerGlobalHeaderOpenApiCustomizer() {
    +    return openApi -> openApi.getPaths().values().stream().flatMap(pathItem -> pathItem.readOperations().stream())
    +            .forEach(operation -> operation.addParametersItem(new HeaderParameter().$ref("#/components/parameters/myGlobalHeader")));
     }
     
    @@ -1307,11 +1305,6 @@

    @@ -1548,20 +1541,25 @@

    For testing purposes only, you can test temporarily using the last springdoc-openapi SNAPSHOT

  • -

    To achieve that, you can on your pom.xml or your settings.xml the following section:

    +

    To achieve that, configure your pom.xml file with the following <repositories> section:

  • -
         <repositories>
    -       <repository>
    -         <id>snapshots-repo</id>
    -         <url>https://s01.oss.sonatype.org/content/repositories/snapshots</url>
    -         <releases><enabled>false</enabled></releases>
    -         <snapshots><enabled>true</enabled></snapshots>
    -       </repository>
    -     </repositories>
    +
        <repositories>
    +      <repository>
    +        <name>Central Portal Snapshots</name>
    +        <id>central-portal-snapshots</id>
    +        <url>https://central.sonatype.com/repository/maven-snapshots/</url>
    +        <releases>
    +          <enabled>false</enabled>
    +        </releases>
    +        <snapshots>
    +          <enabled>true</enabled>
    +        </snapshots>
    +      </repository>
    +    </repositories>
    @@ -1998,25 +1996,13 @@

    - - - diff --git a/docs/v1/features.html b/docs/v1/features.html index 504dae1..e53a7f8 100644 --- a/docs/v1/features.html +++ b/docs/v1/features.html @@ -335,25 +335,13 @@

    - - - diff --git a/docs/v1/getting-started.html b/docs/v1/getting-started.html index f85a6f9..6b3183e 100644 --- a/docs/v1/getting-started.html +++ b/docs/v1/getting-started.html @@ -69,7 +69,7 @@

    Getting S
  • -

    Documentation can be available in yaml format as well, on the following path : /v3/api-docs.yaml

    +

    Documentation will be available in yaml format as well, on the following path : /v3/api-docs.yaml

  • @@ -91,24 +91,12 @@

    Getting S springdoc.swagger-ui.path=/swagger-ui.html - - - - diff --git a/docs/v1/img/LVM_Versicherung_2010_logo.svg.png b/docs/v1/img/LVM_Versicherung_2010_logo.svg.png new file mode 100644 index 0000000..5aac7e9 Binary files /dev/null and b/docs/v1/img/LVM_Versicherung_2010_logo.svg.png differ diff --git a/docs/v1/img/gdnext.png b/docs/v1/img/gdnext.png new file mode 100644 index 0000000..1523834 Binary files /dev/null and b/docs/v1/img/gdnext.png differ diff --git a/docs/v1/img/jetbrains.svg b/docs/v1/img/jetbrains.svg index 75d4d21..cb3a2a0 100644 --- a/docs/v1/img/jetbrains.svg +++ b/docs/v1/img/jetbrains.svg @@ -1,66 +1,13 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/docs/v1/img/springdoc/springdoc-favicon.svg b/docs/v1/img/springdoc/springdoc-favicon.svg new file mode 100644 index 0000000..21eeef6 --- /dev/null +++ b/docs/v1/img/springdoc/springdoc-favicon.svg @@ -0,0 +1,166 @@ + + + + Created with Fabric.js 4.6.0 diff --git a/docs/v1/img/springdoc/springdoc-logo.svg b/docs/v1/img/springdoc/springdoc-logo.svg new file mode 100644 index 0000000..f3f7bb8 --- /dev/null +++ b/docs/v1/img/springdoc/springdoc-logo.svg @@ -0,0 +1,139 @@ + + + + Created with Fabric.js 4.6.0 diff --git a/docs/v1/index.html b/docs/v1/index.html index d022be8..455ec00 100644 --- a/docs/v1/index.html +++ b/docs/v1/index.html @@ -12,6 +12,16 @@ display: none } + + + + @@ -215,6 +225,12 @@

    springdoc-openapi v1.8.0

    + + + + + +

    @@ -265,18 +281,6 @@

    1. Introduction

    This is a community-based project, not maintained by the Spring Framework Contributors (Pivotal).

    - - - -
    @@ -319,7 +323,7 @@

    2. Gettin

  • -

    Documentation can be available in yaml format as well, on the following path : /v3/api-docs.yaml

    +

    Documentation will be available in yaml format as well, on the following path : /v3/api-docs.yaml

  • @@ -341,18 +345,6 @@

    2. Gettin springdoc.swagger-ui.path=/swagger-ui.html - - - - - - - - @@ -1205,18 +1185,6 @@

    - - - @@ -1323,11 +1291,6 @@

    Boolean. When true, automatically adds @ControllerAdvice responses to all the generated responses.

    -

    springdoc.api-docs.groups.enabled

    -

    true

    -

    Boolean. To disable the springdoc-openapi groups.

    - -

    springdoc.group-configs[0].group

    String.The group name

    @@ -1494,18 +1457,6 @@

    - - -

    5.2. swagger-ui properties

    @@ -1567,12 +1518,12 @@

    <

    springdoc.swagger-ui.validatorUrl

    -

    validator.swagger.io/validator

    -

    By default, Swagger UI attempts to validate specs against swagger.io’s online validator. You can use this parameter to set a different validator URL, for example for locally deployed validators Validator Badge. Setting it to either none, 127.0.0.1 or localhost will disable validation.

    + +

    By default, Swagger UI does not validate specs. You can use this parameter to set a validator URL, for example for against swagger.io’s online validator.

    springdoc.swagger-ui.tryItOutEnabled

    -

    false

    +

    true

    Boolean. Controls whether the "Try it out" section should be enabled by default.

    @@ -1653,7 +1604,7 @@

    <

    springdoc.swagger-ui.supportedSubmitMethods

    -

    Array=["get", "put", "post", "delete", "options", "head", "patch", "trace"]. List of HTTP methods that have the "Try it out" feature enabled. An empty array disables "Try it out" for all operations. This does not filter the operations from the display.

    +

    Array=[get, put, post, delete, options, head, patch, trace]. List of HTTP methods that have the "Try it out" feature enabled. An empty array disables "Try it out" for all operations. This does not filter the operations from the display.

    springdoc.swagger-ui.queryConfigEnabled

    @@ -1767,18 +1718,6 @@

    < - - - -

    @@ -1824,7 +1763,7 @@

    6.1. Maven plug <plugin> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-maven-plugin</artifactId> - <version>1.4</version> + <version>1.5</version> <executions> <execution> <id>integration-test</id> @@ -1889,18 +1828,6 @@

    6.2. Gradle p - - - - @@ -1952,18 +1879,6 @@

    - - - @@ -2009,7 +1924,7 @@

    - - - @@ -2220,22 +2120,10 @@

    - - - - @@ -2264,6 +2152,12 @@

    + + + + + +

    10.1. Benefits of being a bronze sponsor

    @@ -2321,18 +2215,6 @@

    - - -

    @@ -2351,21 +2233,9 @@

    11. Special Thanks

    -JetBrains +JetBrains logo
    - - - - @@ -2637,15 +2507,13 @@

    -
    ---
    -@Bean
    +
    @Bean
     @Primary
     fun swaggerUiConfig(config: SwaggerUiConfigProperties): SwaggerUiConfigProperties {
         config.showCommonExtensions = true
         config.queryConfigEnabled = true
         return config
     }
    ----
     
    @@ -2994,7 +2862,7 @@

    @@ -3004,9 +2872,9 @@

    @Bean
    -public OpenApiCustomiser consumerTypeHeaderOpenAPICustomiser() {
    -return openApi -> openApi.getPaths().values().stream().flatMap(pathItem -> pathItem.readOperations().stream())
    -    .forEach(operation -> operation.addParametersItem(new HeaderParameter().$ref("#/components/parameters/myConsumerTypeHeader")));
    +public OpenApiCustomizer customerGlobalHeaderOpenApiCustomizer() {
    +    return openApi -> openApi.getPaths().values().stream().flatMap(pathItem -> pathItem.readOperations().stream())
    +            .forEach(operation -> operation.addParametersItem(new HeaderParameter().$ref("#/components/parameters/myGlobalHeader")));
     }
     
    @@ -3646,11 +3514,6 @@

    @@ -3887,20 +3750,25 @@

    For testing purposes only, you can test temporarily using the last springdoc-openapi SNAPSHOT

  • -

    To achieve that, you can on your pom.xml or your settings.xml the following section:

    +

    To achieve that, configure your pom.xml file with the following <repositories> section:

  • -
         <repositories>
    -       <repository>
    -         <id>snapshots-repo</id>
    -         <url>https://s01.oss.sonatype.org/content/repositories/snapshots</url>
    -         <releases><enabled>false</enabled></releases>
    -         <snapshots><enabled>true</enabled></snapshots>
    -       </repository>
    -     </repositories>
    +
        <repositories>
    +      <repository>
    +        <name>Central Portal Snapshots</name>
    +        <id>central-portal-snapshots</id>
    +        <url>https://central.sonatype.com/repository/maven-snapshots/</url>
    +        <releases>
    +          <enabled>false</enabled>
    +        </releases>
    +        <snapshots>
    +          <enabled>true</enabled>
    +        </snapshots>
    +      </repository>
    +    </repositories>
    @@ -4337,65 +4205,15 @@

    - - - - - - - - - - - - diff --git a/docs/v1/intro.html b/docs/v1/intro.html index cad598d..5f657ae 100644 --- a/docs/v1/intro.html +++ b/docs/v1/intro.html @@ -76,24 +76,12 @@

    Introduction

    This is a community-based project, not maintained by the Spring Framework Contributors (Pivotal).

    - - - - diff --git a/docs/v1/migrating-from-springfox.html b/docs/v1/migrating-from-springfox.html index 7623a51..c9ae792 100644 --- a/docs/v1/migrating-from-springfox.html +++ b/docs/v1/migrating-from-springfox.html @@ -71,7 +71,7 @@

    - - - diff --git a/docs/v1/modules.html b/docs/v1/modules.html index 8d4600c..2d57b67 100644 --- a/docs/v1/modules.html +++ b/docs/v1/modules.html @@ -113,7 +113,7 @@

    • -

      Documentation can be available in yaml format as well, on the following path : /v3/api-docs.yaml

      +

      Documentation will be available in yaml format as well, on the following path : /v3/api-docs.yaml

    • Add the library to the list of your project dependencies (No additional configuration is needed)

      @@ -558,25 +558,13 @@

      Javadoc - - - - diff --git a/docs/v1/other-resources.html b/docs/v1/other-resources.html index b2ddea8..13b49b7 100644 --- a/docs/v1/other-resources.html +++ b/docs/v1/other-resources.html @@ -37,9 +37,6 @@

      - - - - diff --git a/docs/v1/privacy-policy.html b/docs/v1/privacy-policy.html index a1a71b5..cb9f032 100644 --- a/docs/v1/privacy-policy.html +++ b/docs/v1/privacy-policy.html @@ -252,22 +252,10 @@

      If you have any questions or concerns about this Policy or its implementation, you may contact us at support@springdoc.org.

      - - - - diff --git a/docs/v1/properties.html b/docs/v1/properties.html index 1569b0a..27ff29f 100644 --- a/docs/v1/properties.html +++ b/docs/v1/properties.html @@ -64,37 +64,37 @@

      springdoc.packages-to-scan

      *

      -

      List of Strings.The list of packages to scan (comma separated)

      +

      List of Strings. The list of packages to scan (comma separated)

      springdoc.paths-to-match

      /*

      -

      List of Strings.The list of paths to match (comma separated)

      +

      List of Strings. The list of paths to match (comma separated)

      springdoc.produces-to-match

      /*

      -

      List of Strings.The list of produces mediaTypes to match (comma separated)

      +

      List of Strings. The list of produces mediaTypes to match (comma separated)

      springdoc.headers-to-match

      /*

      -

      List of Strings.The list of headers to match (comma separated)

      +

      List of Strings. The list of headers to match (comma separated)

      springdoc.consumes-to-match

      /*

      -

      List of Strings.The list of consumes mediaTypes to match (comma separated)

      +

      List of Strings. The list of consumes mediaTypes to match (comma separated)

      springdoc.paths-to-exclude

      -

      List of Strings.The list of paths to exclude (comma separated)

      +

      List of Strings. The list of paths to exclude (comma separated)

      springdoc.packages-to-exclude

      -

      List of Strings.The list of packages to exclude (comma separated)

      +

      List of Strings. The list of packages to exclude (comma separated)

      springdoc.default-consumes-media-type

      @@ -104,7 +104,7 @@

      springdoc.default-produces-media-type

      /

      -

      String.The default produces media type.

      +

      String. The default produces media type.

      springdoc.cache.disabled

      @@ -132,59 +132,54 @@

      Boolean. When true, automatically adds @ControllerAdvice responses to all the generated responses.

      -

      springdoc.api-docs.groups.enabled

      -

      true

      -

      Boolean. To disable the springdoc-openapi groups.

      - -

      springdoc.group-configs[0].group

      -

      String.The group name

      +

      String. The group name

      springdoc.group-configs[0].display-name

      -

      String.The display name of the group.

      +

      String. The display name of the group.

      springdoc.group-configs[0].packages-to-scan

      *

      -

      List of Strings.The list of packages to scan for a group (comma separated)

      +

      List of Strings. The list of packages to scan for a group (comma separated)

      springdoc.group-configs[0].paths-to-match

      /*

      -

      List of Strings.The list of paths to match for a group(comma separated)

      +

      List of Strings. The list of paths to match for a group (comma separated)

      springdoc.group-configs[0].paths-to-exclude

      ``

      -

      List of Strings.The list of paths to exclude for a group(comma separated)

      +

      List of Strings. The list of paths to exclude for a group (comma separated)

      springdoc.group-configs[0].packages-to-exclude

      -

      List of Strings.The list of packages to exclude for a group(comma separated)

      +

      List of Strings. The list of packages to exclude for a group (comma separated)

      springdoc.group-configs[0].produces-to-match

      /*

      -

      List of Strings.The list of produces mediaTypes to match (comma separated)

      +

      List of Strings. The list of produces mediaTypes to match (comma separated)

      springdoc.group-configs[0].consumes-to-match

      /*

      -

      List of Strings.The list of consumes mediaTypes to match (comma separated)

      +

      List of Strings. The list of consumes mediaTypes to match (comma separated)

      springdoc.group-configs[0].headers-to-match

      /*

      -

      List of Strings.The list of headers to match (comma separated)

      +

      List of Strings. The list of headers to match (comma separated)

      springdoc.webjars.prefix

      /webjars

      -

      String, To change the webjars prefix that is visible the URL of swagger-ui for spring-webflux.

      +

      String. To change the webjars prefix that is visible the URL of swagger-ui for spring-webflux.

      springdoc.api-docs.resolve-schema-properties

      @@ -232,14 +227,9 @@

      Boolean. To make spring security login-endpoint visible.

      -

      springdoc.pre-loading-enabled

      -

      false

      -

      Boolean. Pre-loading setting to load OpenAPI on application startup.

      - -

      springdoc.pre-loading-locales

      -

      List of Strings.The list of locales to load OpenAPI on application startup.(comma separated) If not specified, it will preload with the default Locale.

      +

      List of Strings. The list of locales to load OpenAPI on application startup (comma separated). If not specified, it will preload with the default Locale.

      springdoc.writer-with-order-by-keys

      @@ -274,7 +264,7 @@

      springdoc.enable-kotlin

      true

      -

      Boolproperty resolver on @Schema (extensionean. To enable Kotlin support.

      +

      Boolean. To enable Kotlin support.

      springdoc.enable-hateoas

      @@ -288,8 +278,8 @@

      springdoc.api-docs.version

      -

      openapi_3_0

      -

      String. To Choose OpenAPI 3.0 or OpenAPI 3.1 (using the value OPENAPI_3_1).

      +

      openapi_3_1

      +

      String. To choose OpenAPI 3.0 or OpenAPI 3.1 (using the value OPENAPI_3_1).

      springdoc.default-flat-param-object

      @@ -326,20 +316,28 @@

      false

      Boolean. Adjust indentation when parsing the @Operation annotation in Kotlin.

      + +

      springdoc.allowed-locales

      + +

      List of Strings. The list of allowed locales for OpenAPI (comma separated, for example US,fr-CA).

      + + +

      springdoc.enable-extra-schemas

      +

      true

      +

      Boolean. To enable default support for extra Schemas, from java.time package like LocalTime, Duration, but also other Java classes like java.util.Locale or java.nio.charset.Charset

      + + +

      springdoc.explicit-object-schema

      +

      false

      +

      Boolean. Set explicit-object-schema to true to always include type: object in the schema, or to false to omit type: object.

      + + +

      springdoc.use-arbitrary-schemas

      +

      false

      +

      Boolean. When set to true, schemas without a defined type will be deserialized as an ArbitrarySchema (with no type), instead of an ObjectSchema with type: object.

      + - - - -
      diff --git a/docs/v1/sponsor.html b/docs/v1/sponsor.html index 1f2b62f..a996f61 100644 --- a/docs/v1/sponsor.html +++ b/docs/v1/sponsor.html @@ -54,6 +54,12 @@ + + + + + +

      Benefits of being a bronze sponsor

      @@ -111,25 +117,13 @@

      - - -

      diff --git a/docs/v1/thanks.html b/docs/v1/thanks.html index 87fa9e2..10bd2e6 100644 --- a/docs/v1/thanks.html +++ b/docs/v1/thanks.html @@ -44,27 +44,15 @@

      Special Thanks

      -JetBrains +JetBrains logo
      - - - - diff --git a/docs/v1/ui-properties.html b/docs/v1/ui-properties.html index 9a927f6..7f559fa 100644 --- a/docs/v1/ui-properties.html +++ b/docs/v1/ui-properties.html @@ -65,12 +65,12 @@

      springdoc.swagger-ui.validatorUrl

      -

      https://validator.swagger.io/validator

      -

      By default, Swagger UI attempts to validate specs against swagger.io’s online validator. You can use this parameter to set a different validator URL, for example for locally deployed validators Validator Badge. Setting it to either none, 127.0.0.1 or localhost will disable validation.

      + +

      By default, Swagger UI does not validate specs. You can use this parameter to set a validator URL, for example for against swagger.io’s online validator.

      springdoc.swagger-ui.tryItOutEnabled

      -

      false

      +

      true

      Boolean. Controls whether the "Try it out" section should be enabled by default.

      @@ -151,7 +151,7 @@

      springdoc.swagger-ui.supportedSubmitMethods

      -

      Array=["get", "put", "post", "delete", "options", "head", "patch", "trace"]. List of HTTP methods that have the "Try it out" feature enabled. An empty array disables "Try it out" for all operations. This does not filter the operations from the display.

      +

      Array=[get, put, post, delete, options, head, patch, trace]. List of HTTP methods that have the "Try it out" feature enabled. An empty array disables "Try it out" for all operations. This does not filter the operations from the display.

      springdoc.swagger-ui.queryConfigEnabled

      @@ -265,22 +265,10 @@ - - - - diff --git a/docs/v4/core-properties.html b/docs/v4/core-properties.html new file mode 100644 index 0000000..b5577ab --- /dev/null +++ b/docs/v4/core-properties.html @@ -0,0 +1,343 @@ + + + + + + + +Untitled + + + + + + +
      +
      +
      + +
      + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Parameter nameDefault ValueDescription

      springdoc.api-docs.path

      /v3/api-docs

      String, For custom path of the OpenAPI documentation in Json format.

      springdoc.api-docs.enabled

      true

      Boolean. To disable the springdoc-openapi endpoint (/v3/api-docs by default).

      springdoc.packages-to-scan

      *

      List of Strings. The list of packages to scan (comma separated)

      springdoc.paths-to-match

      /*

      List of Strings. The list of paths to match (comma separated)

      springdoc.produces-to-match

      /*

      List of Strings. The list of produces mediaTypes to match (comma separated)

      springdoc.headers-to-match

      /*

      List of Strings. The list of headers to match (comma separated)

      springdoc.consumes-to-match

      /*

      List of Strings. The list of consumes mediaTypes to match (comma separated)

      springdoc.paths-to-exclude

      List of Strings. The list of paths to exclude (comma separated)

      springdoc.packages-to-exclude

      List of Strings. The list of packages to exclude (comma separated)

      springdoc.default-consumes-media-type

      application/json

      String. The default consumes media type.

      springdoc.default-produces-media-type

      /

      String. The default produces media type.

      springdoc.cache.disabled

      false

      Boolean. To disable the springdoc-openapi cache of the calculated OpenAPI.

      springdoc.show-actuator

      false

      Boolean. To display the actuator endpoints.

      springdoc.auto-tag-classes

      true

      Boolean. To disable the springdoc-openapi automatic tags.

      springdoc.model-and-view-allowed

      false

      Boolean. To allow RestControllers with ModelAndView return to appear in the OpenAPI description.

      springdoc.override-with-generic-response

      true

      Boolean. When true, automatically adds @ControllerAdvice responses to all the generated responses.

      springdoc.group-configs[0].group

      String. The group name

      springdoc.group-configs[0].display-name

      String. The display name of the group.

      springdoc.group-configs[0].packages-to-scan

      *

      List of Strings. The list of packages to scan for a group (comma separated)

      springdoc.group-configs[0].paths-to-match

      /*

      List of Strings. The list of paths to match for a group (comma separated)

      springdoc.group-configs[0].paths-to-exclude

      ``

      List of Strings. The list of paths to exclude for a group (comma separated)

      springdoc.group-configs[0].packages-to-exclude

      List of Strings. The list of packages to exclude for a group (comma separated)

      springdoc.group-configs[0].produces-to-match

      /*

      List of Strings. The list of produces mediaTypes to match (comma separated)

      springdoc.group-configs[0].consumes-to-match

      /*

      List of Strings. The list of consumes mediaTypes to match (comma separated)

      springdoc.group-configs[0].headers-to-match

      /*

      List of Strings. The list of headers to match (comma separated)

      springdoc.webjars.prefix

      /webjars

      String. To change the webjars prefix that is visible the URL of swagger-ui for spring-webflux.

      springdoc.api-docs.resolve-schema-properties

      false

      Boolean. To enable property resolver on @Schema (name, title and description).

      springdoc.remove-broken-reference-definitions

      true

      Boolean. To disable removal of broken reference definitions.

      springdoc.writer-with-default-pretty-printer

      false

      Boolean. To enable pretty print of the OpenApi specification.

      springdoc.model-converters.deprecating-converter.enabled

      true

      Boolean. To disable deprecating model converter.

      springdoc.model-converters.polymorphic-converter.enabled

      true

      Boolean. To disable polymorphic model converter.

      springdoc.model-converters.pageable-converter.enabled

      true

      Boolean. To disable pageable model converter.

      springdoc.model-converters.sort-converter.enabled

      true

      Boolean. To disable Sort converter.

      springdoc.use-fqn

      false

      Boolean. To enable fully qualified names.

      springdoc.show-login-endpoint

      false

      Boolean. To make spring security login-endpoint visible.

      springdoc.pre-loading-locales

      List of Strings. The list of locales to load OpenAPI on application startup (comma separated). If not specified, it will preload with the default Locale.

      springdoc.writer-with-order-by-keys

      false

      Boolean. Enable a deterministic/alphabetical ordering.

      springdoc.use-management-port

      false

      Boolean. To expose the swagger-ui on the actuator management port.

      springdoc.disable-i18n

      false

      Boolean. To disable automatic translation using i18n.

      springdoc.show-spring-cloud-functions

      true

      Boolean. To display the spring-cloud-function web endpoints.

      springdoc.enable-groovy

      true

      Boolean. To enable Groovy support.

      springdoc.enable-spring-security

      true

      Boolean. To enable spring-security support.

      springdoc.enable-kotlin

      true

      Boolean. To enable Kotlin support.

      springdoc.enable-hateoas

      true

      Boolean. To enable spring-hateoas support.

      springdoc.enable-data-rest

      true

      Boolean. To enable spring-data-rest support.

      springdoc.api-docs.version

      openapi_3_1

      String. To choose OpenAPI 3.0 or OpenAPI 3.1 (using the value OPENAPI_3_1).

      springdoc.default-flat-param-object

      false

      Boolean. To default flatten parameter.

      springdoc.default-support-form-data

      false

      Boolean. To default set parameters to form data when specifying api to accept form data.

      springdoc.nullable-request-parameter-enabled

      true

      Boolean. To default Enable Support for nullable request parameters in Kotlin.

      springdoc.show-oauth2-endpoints

      false

      Boolean. To make spring security oauth2-endpoint visible.

      springdoc.api-docs.resolve-extensions-properties

      false

      Boolean. To enable support of spring property resolver for @ExtensionProperty.

      springdoc.enable-default-api-docs

      true

      Boolean. To enable default OpenAPI endpoint /v3/api-docs.

      springdoc.trim-kotlin-indent

      false

      Boolean. Adjust indentation when parsing the @Operation annotation in Kotlin.

      springdoc.allowed-locales

      List of Strings. The list of allowed locales for OpenAPI (comma separated, for example US,fr-CA).

      springdoc.enable-extra-schemas

      true

      Boolean. To enable default support for extra Schemas, from java.time package like LocalTime, Duration, but also other Java classes like java.util.Locale or java.nio.charset.Charset

      springdoc.explicit-object-schema

      false

      Boolean. Set explicit-object-schema to true to always include type: object in the schema, or to false to omit type: object.

      springdoc.use-arbitrary-schemas

      false

      Boolean. When set to true, schemas without a defined type will be deserialized as an ArbitrarySchema (with no type), instead of an ObjectSchema with type: object.

      +
      + +
      +
      +
      + + \ No newline at end of file diff --git a/docs/v4/css/font-awesome.css b/docs/v4/css/font-awesome.css new file mode 100644 index 0000000..ee906a8 --- /dev/null +++ b/docs/v4/css/font-awesome.css @@ -0,0 +1,2337 @@ +/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */ +/* FONT PATH + * -------------------------- */ +@font-face { + font-family: 'FontAwesome'; + src: url('../fonts/fontawesome-webfont.eot?v=4.7.0'); + src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg'); + font-weight: normal; + font-style: normal; +} +.fa { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +/* makes the font 33% larger relative to the icon container */ +.fa-lg { + font-size: 1.33333333em; + line-height: 0.75em; + vertical-align: -15%; +} +.fa-2x { + font-size: 2em; +} +.fa-3x { + font-size: 3em; +} +.fa-4x { + font-size: 4em; +} +.fa-5x { + font-size: 5em; +} +.fa-fw { + width: 1.28571429em; + text-align: center; +} +.fa-ul { + padding-left: 0; + margin-left: 2.14285714em; + list-style-type: none; +} +.fa-ul > li { + position: relative; +} +.fa-li { + position: absolute; + left: -2.14285714em; + width: 2.14285714em; + top: 0.14285714em; + text-align: center; +} +.fa-li.fa-lg { + left: -1.85714286em; +} +.fa-border { + padding: .2em .25em .15em; + border: solid 0.08em #eeeeee; + border-radius: .1em; +} +.fa-pull-left { + float: left; +} +.fa-pull-right { + float: right; +} +.fa.fa-pull-left { + margin-right: .3em; +} +.fa.fa-pull-right { + margin-left: .3em; +} +/* Deprecated as of 4.4.0 */ +.pull-right { + float: right; +} +.pull-left { + float: left; +} +.fa.pull-left { + margin-right: .3em; +} +.fa.pull-right { + margin-left: .3em; +} +.fa-spin { + -webkit-animation: fa-spin 2s infinite linear; + animation: fa-spin 2s infinite linear; +} +.fa-pulse { + -webkit-animation: fa-spin 1s infinite steps(8); + animation: fa-spin 1s infinite steps(8); +} +@-webkit-keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +@keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +.fa-rotate-90 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)"; + -webkit-transform: rotate(90deg); + -ms-transform: rotate(90deg); + transform: rotate(90deg); +} +.fa-rotate-180 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)"; + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} +.fa-rotate-270 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)"; + -webkit-transform: rotate(270deg); + -ms-transform: rotate(270deg); + transform: rotate(270deg); +} +.fa-flip-horizontal { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)"; + -webkit-transform: scale(-1, 1); + -ms-transform: scale(-1, 1); + transform: scale(-1, 1); +} +.fa-flip-vertical { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; + -webkit-transform: scale(1, -1); + -ms-transform: scale(1, -1); + transform: scale(1, -1); +} +:root .fa-rotate-90, +:root .fa-rotate-180, +:root .fa-rotate-270, +:root .fa-flip-horizontal, +:root .fa-flip-vertical { + filter: none; +} +.fa-stack { + position: relative; + display: inline-block; + width: 2em; + height: 2em; + line-height: 2em; + vertical-align: middle; +} +.fa-stack-1x, +.fa-stack-2x { + position: absolute; + left: 0; + width: 100%; + text-align: center; +} +.fa-stack-1x { + line-height: inherit; +} +.fa-stack-2x { + font-size: 2em; +} +.fa-inverse { + color: #ffffff; +} +/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen + readers do not read off random characters that represent icons */ +.fa-glass:before { + content: "\f000"; +} +.fa-music:before { + content: "\f001"; +} +.fa-search:before { + content: "\f002"; +} +.fa-envelope-o:before { + content: "\f003"; +} +.fa-heart:before { + content: "\f004"; +} +.fa-star:before { + content: "\f005"; +} +.fa-star-o:before { + content: "\f006"; +} +.fa-user:before { + content: "\f007"; +} +.fa-film:before { + content: "\f008"; +} +.fa-th-large:before { + content: "\f009"; +} +.fa-th:before { + content: "\f00a"; +} +.fa-th-list:before { + content: "\f00b"; +} +.fa-check:before { + content: "\f00c"; +} +.fa-remove:before, +.fa-close:before, +.fa-times:before { + content: "\f00d"; +} +.fa-search-plus:before { + content: "\f00e"; +} +.fa-search-minus:before { + content: "\f010"; +} +.fa-power-off:before { + content: "\f011"; +} +.fa-signal:before { + content: "\f012"; +} +.fa-gear:before, +.fa-cog:before { + content: "\f013"; +} +.fa-trash-o:before { + content: "\f014"; +} +.fa-home:before { + content: "\f015"; +} +.fa-file-o:before { + content: "\f016"; +} +.fa-clock-o:before { + content: "\f017"; +} +.fa-road:before { + content: "\f018"; +} +.fa-download:before { + content: "\f019"; +} +.fa-arrow-circle-o-down:before { + content: "\f01a"; +} +.fa-arrow-circle-o-up:before { + content: "\f01b"; +} +.fa-inbox:before { + content: "\f01c"; +} +.fa-play-circle-o:before { + content: "\f01d"; +} +.fa-rotate-right:before, +.fa-repeat:before { + content: "\f01e"; +} +.fa-refresh:before { + content: "\f021"; +} +.fa-list-alt:before { + content: "\f022"; +} +.fa-lock:before { + content: "\f023"; +} +.fa-flag:before { + content: "\f024"; +} +.fa-headphones:before { + content: "\f025"; +} +.fa-volume-off:before { + content: "\f026"; +} +.fa-volume-down:before { + content: "\f027"; +} +.fa-volume-up:before { + content: "\f028"; +} +.fa-qrcode:before { + content: "\f029"; +} +.fa-barcode:before { + content: "\f02a"; +} +.fa-tag:before { + content: "\f02b"; +} +.fa-tags:before { + content: "\f02c"; +} +.fa-book:before { + content: "\f02d"; +} +.fa-bookmark:before { + content: "\f02e"; +} +.fa-print:before { + content: "\f02f"; +} +.fa-camera:before { + content: "\f030"; +} +.fa-font:before { + content: "\f031"; +} +.fa-bold:before { + content: "\f032"; +} +.fa-italic:before { + content: "\f033"; +} +.fa-text-height:before { + content: "\f034"; +} +.fa-text-width:before { + content: "\f035"; +} +.fa-align-left:before { + content: "\f036"; +} +.fa-align-center:before { + content: "\f037"; +} +.fa-align-right:before { + content: "\f038"; +} +.fa-align-justify:before { + content: "\f039"; +} +.fa-list:before { + content: "\f03a"; +} +.fa-dedent:before, +.fa-outdent:before { + content: "\f03b"; +} +.fa-indent:before { + content: "\f03c"; +} +.fa-video-camera:before { + content: "\f03d"; +} +.fa-photo:before, +.fa-image:before, +.fa-picture-o:before { + content: "\f03e"; +} +.fa-pencil:before { + content: "\f040"; +} +.fa-map-marker:before { + content: "\f041"; +} +.fa-adjust:before { + content: "\f042"; +} +.fa-tint:before { + content: "\f043"; +} +.fa-edit:before, +.fa-pencil-square-o:before { + content: "\f044"; +} +.fa-share-square-o:before { + content: "\f045"; +} +.fa-check-square-o:before { + content: "\f046"; +} +.fa-arrows:before { + content: "\f047"; +} +.fa-step-backward:before { + content: "\f048"; +} +.fa-fast-backward:before { + content: "\f049"; +} +.fa-backward:before { + content: "\f04a"; +} +.fa-play:before { + content: "\f04b"; +} +.fa-pause:before { + content: "\f04c"; +} +.fa-stop:before { + content: "\f04d"; +} +.fa-forward:before { + content: "\f04e"; +} +.fa-fast-forward:before { + content: "\f050"; +} +.fa-step-forward:before { + content: "\f051"; +} +.fa-eject:before { + content: "\f052"; +} +.fa-chevron-left:before { + content: "\f053"; +} +.fa-chevron-right:before { + content: "\f054"; +} +.fa-plus-circle:before { + content: "\f055"; +} +.fa-minus-circle:before { + content: "\f056"; +} +.fa-times-circle:before { + content: "\f057"; +} +.fa-check-circle:before { + content: "\f058"; +} +.fa-question-circle:before { + content: "\f059"; +} +.fa-info-circle:before { + content: "\f05a"; +} +.fa-crosshairs:before { + content: "\f05b"; +} +.fa-times-circle-o:before { + content: "\f05c"; +} +.fa-check-circle-o:before { + content: "\f05d"; +} +.fa-ban:before { + content: "\f05e"; +} +.fa-arrow-left:before { + content: "\f060"; +} +.fa-arrow-right:before { + content: "\f061"; +} +.fa-arrow-up:before { + content: "\f062"; +} +.fa-arrow-down:before { + content: "\f063"; +} +.fa-mail-forward:before, +.fa-share:before { + content: "\f064"; +} +.fa-expand:before { + content: "\f065"; +} +.fa-compress:before { + content: "\f066"; +} +.fa-plus:before { + content: "\f067"; +} +.fa-minus:before { + content: "\f068"; +} +.fa-asterisk:before { + content: "\f069"; +} +.fa-exclamation-circle:before { + content: "\f06a"; +} +.fa-gift:before { + content: "\f06b"; +} +.fa-leaf:before { + content: "\f06c"; +} +.fa-fire:before { + content: "\f06d"; +} +.fa-eye:before { + content: "\f06e"; +} +.fa-eye-slash:before { + content: "\f070"; +} +.fa-warning:before, +.fa-exclamation-triangle:before { + content: "\f071"; +} +.fa-plane:before { + content: "\f072"; +} +.fa-calendar:before { + content: "\f073"; +} +.fa-random:before { + content: "\f074"; +} +.fa-comment:before { + content: "\f075"; +} +.fa-magnet:before { + content: "\f076"; +} +.fa-chevron-up:before { + content: "\f077"; +} +.fa-chevron-down:before { + content: "\f078"; +} +.fa-retweet:before { + content: "\f079"; +} +.fa-shopping-cart:before { + content: "\f07a"; +} +.fa-folder:before { + content: "\f07b"; +} +.fa-folder-open:before { + content: "\f07c"; +} +.fa-arrows-v:before { + content: "\f07d"; +} +.fa-arrows-h:before { + content: "\f07e"; +} +.fa-bar-chart-o:before, +.fa-bar-chart:before { + content: "\f080"; +} +.fa-twitter-square:before { + content: "\f081"; +} +.fa-facebook-square:before { + content: "\f082"; +} +.fa-camera-retro:before { + content: "\f083"; +} +.fa-key:before { + content: "\f084"; +} +.fa-gears:before, +.fa-cogs:before { + content: "\f085"; +} +.fa-comments:before { + content: "\f086"; +} +.fa-thumbs-o-up:before { + content: "\f087"; +} +.fa-thumbs-o-down:before { + content: "\f088"; +} +.fa-star-half:before { + content: "\f089"; +} +.fa-heart-o:before { + content: "\f08a"; +} +.fa-sign-out:before { + content: "\f08b"; +} +.fa-linkedin-square:before { + content: "\f08c"; +} +.fa-thumb-tack:before { + content: "\f08d"; +} +.fa-external-link:before { + content: "\f08e"; +} +.fa-sign-in:before { + content: "\f090"; +} +.fa-trophy:before { + content: "\f091"; +} +.fa-github-square:before { + content: "\f092"; +} +.fa-upload:before { + content: "\f093"; +} +.fa-lemon-o:before { + content: "\f094"; +} +.fa-phone:before { + content: "\f095"; +} +.fa-square-o:before { + content: "\f096"; +} +.fa-bookmark-o:before { + content: "\f097"; +} +.fa-phone-square:before { + content: "\f098"; +} +.fa-twitter:before { + content: "\f099"; +} +.fa-facebook-f:before, +.fa-facebook:before { + content: "\f09a"; +} +.fa-github:before { + content: "\f09b"; +} +.fa-unlock:before { + content: "\f09c"; +} +.fa-credit-card:before { + content: "\f09d"; +} +.fa-feed:before, +.fa-rss:before { + content: "\f09e"; +} +.fa-hdd-o:before { + content: "\f0a0"; +} +.fa-bullhorn:before { + content: "\f0a1"; +} +.fa-bell:before { + content: "\f0f3"; +} +.fa-certificate:before { + content: "\f0a3"; +} +.fa-hand-o-right:before { + content: "\f0a4"; +} +.fa-hand-o-left:before { + content: "\f0a5"; +} +.fa-hand-o-up:before { + content: "\f0a6"; +} +.fa-hand-o-down:before { + content: "\f0a7"; +} +.fa-arrow-circle-left:before { + content: "\f0a8"; +} +.fa-arrow-circle-right:before { + content: "\f0a9"; +} +.fa-arrow-circle-up:before { + content: "\f0aa"; +} +.fa-arrow-circle-down:before { + content: "\f0ab"; +} +.fa-globe:before { + content: "\f0ac"; +} +.fa-wrench:before { + content: "\f0ad"; +} +.fa-tasks:before { + content: "\f0ae"; +} +.fa-filter:before { + content: "\f0b0"; +} +.fa-briefcase:before { + content: "\f0b1"; +} +.fa-arrows-alt:before { + content: "\f0b2"; +} +.fa-group:before, +.fa-users:before { + content: "\f0c0"; +} +.fa-chain:before, +.fa-link:before { + content: "\f0c1"; +} +.fa-cloud:before { + content: "\f0c2"; +} +.fa-flask:before { + content: "\f0c3"; +} +.fa-cut:before, +.fa-scissors:before { + content: "\f0c4"; +} +.fa-copy:before, +.fa-files-o:before { + content: "\f0c5"; +} +.fa-paperclip:before { + content: "\f0c6"; +} +.fa-save:before, +.fa-floppy-o:before { + content: "\f0c7"; +} +.fa-square:before { + content: "\f0c8"; +} +.fa-navicon:before, +.fa-reorder:before, +.fa-bars:before { + content: "\f0c9"; +} +.fa-list-ul:before { + content: "\f0ca"; +} +.fa-list-ol:before { + content: "\f0cb"; +} +.fa-strikethrough:before { + content: "\f0cc"; +} +.fa-underline:before { + content: "\f0cd"; +} +.fa-table:before { + content: "\f0ce"; +} +.fa-magic:before { + content: "\f0d0"; +} +.fa-truck:before { + content: "\f0d1"; +} +.fa-pinterest:before { + content: "\f0d2"; +} +.fa-pinterest-square:before { + content: "\f0d3"; +} +.fa-google-plus-square:before { + content: "\f0d4"; +} +.fa-google-plus:before { + content: "\f0d5"; +} +.fa-money:before { + content: "\f0d6"; +} +.fa-caret-down:before { + content: "\f0d7"; +} +.fa-caret-up:before { + content: "\f0d8"; +} +.fa-caret-left:before { + content: "\f0d9"; +} +.fa-caret-right:before { + content: "\f0da"; +} +.fa-columns:before { + content: "\f0db"; +} +.fa-unsorted:before, +.fa-sort:before { + content: "\f0dc"; +} +.fa-sort-down:before, +.fa-sort-desc:before { + content: "\f0dd"; +} +.fa-sort-up:before, +.fa-sort-asc:before { + content: "\f0de"; +} +.fa-envelope:before { + content: "\f0e0"; +} +.fa-linkedin:before { + content: "\f0e1"; +} +.fa-rotate-left:before, +.fa-undo:before { + content: "\f0e2"; +} +.fa-legal:before, +.fa-gavel:before { + content: "\f0e3"; +} +.fa-dashboard:before, +.fa-tachometer:before { + content: "\f0e4"; +} +.fa-comment-o:before { + content: "\f0e5"; +} +.fa-comments-o:before { + content: "\f0e6"; +} +.fa-flash:before, +.fa-bolt:before { + content: "\f0e7"; +} +.fa-sitemap:before { + content: "\f0e8"; +} +.fa-umbrella:before { + content: "\f0e9"; +} +.fa-paste:before, +.fa-clipboard:before { + content: "\f0ea"; +} +.fa-lightbulb-o:before { + content: "\f0eb"; +} +.fa-exchange:before { + content: "\f0ec"; +} +.fa-cloud-download:before { + content: "\f0ed"; +} +.fa-cloud-upload:before { + content: "\f0ee"; +} +.fa-user-md:before { + content: "\f0f0"; +} +.fa-stethoscope:before { + content: "\f0f1"; +} +.fa-suitcase:before { + content: "\f0f2"; +} +.fa-bell-o:before { + content: "\f0a2"; +} +.fa-coffee:before { + content: "\f0f4"; +} +.fa-cutlery:before { + content: "\f0f5"; +} +.fa-file-text-o:before { + content: "\f0f6"; +} +.fa-building-o:before { + content: "\f0f7"; +} +.fa-hospital-o:before { + content: "\f0f8"; +} +.fa-ambulance:before { + content: "\f0f9"; +} +.fa-medkit:before { + content: "\f0fa"; +} +.fa-fighter-jet:before { + content: "\f0fb"; +} +.fa-beer:before { + content: "\f0fc"; +} +.fa-h-square:before { + content: "\f0fd"; +} +.fa-plus-square:before { + content: "\f0fe"; +} +.fa-angle-double-left:before { + content: "\f100"; +} +.fa-angle-double-right:before { + content: "\f101"; +} +.fa-angle-double-up:before { + content: "\f102"; +} +.fa-angle-double-down:before { + content: "\f103"; +} +.fa-angle-left:before { + content: "\f104"; +} +.fa-angle-right:before { + content: "\f105"; +} +.fa-angle-up:before { + content: "\f106"; +} +.fa-angle-down:before { + content: "\f107"; +} +.fa-desktop:before { + content: "\f108"; +} +.fa-laptop:before { + content: "\f109"; +} +.fa-tablet:before { + content: "\f10a"; +} +.fa-mobile-phone:before, +.fa-mobile:before { + content: "\f10b"; +} +.fa-circle-o:before { + content: "\f10c"; +} +.fa-quote-left:before { + content: "\f10d"; +} +.fa-quote-right:before { + content: "\f10e"; +} +.fa-spinner:before { + content: "\f110"; +} +.fa-circle:before { + content: "\f111"; +} +.fa-mail-reply:before, +.fa-reply:before { + content: "\f112"; +} +.fa-github-alt:before { + content: "\f113"; +} +.fa-folder-o:before { + content: "\f114"; +} +.fa-folder-open-o:before { + content: "\f115"; +} +.fa-smile-o:before { + content: "\f118"; +} +.fa-frown-o:before { + content: "\f119"; +} +.fa-meh-o:before { + content: "\f11a"; +} +.fa-gamepad:before { + content: "\f11b"; +} +.fa-keyboard-o:before { + content: "\f11c"; +} +.fa-flag-o:before { + content: "\f11d"; +} +.fa-flag-checkered:before { + content: "\f11e"; +} +.fa-terminal:before { + content: "\f120"; +} +.fa-code:before { + content: "\f121"; +} +.fa-mail-reply-all:before, +.fa-reply-all:before { + content: "\f122"; +} +.fa-star-half-empty:before, +.fa-star-half-full:before, +.fa-star-half-o:before { + content: "\f123"; +} +.fa-location-arrow:before { + content: "\f124"; +} +.fa-crop:before { + content: "\f125"; +} +.fa-code-fork:before { + content: "\f126"; +} +.fa-unlink:before, +.fa-chain-broken:before { + content: "\f127"; +} +.fa-question:before { + content: "\f128"; +} +.fa-info:before { + content: "\f129"; +} +.fa-exclamation:before { + content: "\f12a"; +} +.fa-superscript:before { + content: "\f12b"; +} +.fa-subscript:before { + content: "\f12c"; +} +.fa-eraser:before { + content: "\f12d"; +} +.fa-puzzle-piece:before { + content: "\f12e"; +} +.fa-microphone:before { + content: "\f130"; +} +.fa-microphone-slash:before { + content: "\f131"; +} +.fa-shield:before { + content: "\f132"; +} +.fa-calendar-o:before { + content: "\f133"; +} +.fa-fire-extinguisher:before { + content: "\f134"; +} +.fa-rocket:before { + content: "\f135"; +} +.fa-maxcdn:before { + content: "\f136"; +} +.fa-chevron-circle-left:before { + content: "\f137"; +} +.fa-chevron-circle-right:before { + content: "\f138"; +} +.fa-chevron-circle-up:before { + content: "\f139"; +} +.fa-chevron-circle-down:before { + content: "\f13a"; +} +.fa-html5:before { + content: "\f13b"; +} +.fa-css3:before { + content: "\f13c"; +} +.fa-anchor:before { + content: "\f13d"; +} +.fa-unlock-alt:before { + content: "\f13e"; +} +.fa-bullseye:before { + content: "\f140"; +} +.fa-ellipsis-h:before { + content: "\f141"; +} +.fa-ellipsis-v:before { + content: "\f142"; +} +.fa-rss-square:before { + content: "\f143"; +} +.fa-play-circle:before { + content: "\f144"; +} +.fa-ticket:before { + content: "\f145"; +} +.fa-minus-square:before { + content: "\f146"; +} +.fa-minus-square-o:before { + content: "\f147"; +} +.fa-level-up:before { + content: "\f148"; +} +.fa-level-down:before { + content: "\f149"; +} +.fa-check-square:before { + content: "\f14a"; +} +.fa-pencil-square:before { + content: "\f14b"; +} +.fa-external-link-square:before { + content: "\f14c"; +} +.fa-share-square:before { + content: "\f14d"; +} +.fa-compass:before { + content: "\f14e"; +} +.fa-toggle-down:before, +.fa-caret-square-o-down:before { + content: "\f150"; +} +.fa-toggle-up:before, +.fa-caret-square-o-up:before { + content: "\f151"; +} +.fa-toggle-right:before, +.fa-caret-square-o-right:before { + content: "\f152"; +} +.fa-euro:before, +.fa-eur:before { + content: "\f153"; +} +.fa-gbp:before { + content: "\f154"; +} +.fa-dollar:before, +.fa-usd:before { + content: "\f155"; +} +.fa-rupee:before, +.fa-inr:before { + content: "\f156"; +} +.fa-cny:before, +.fa-rmb:before, +.fa-yen:before, +.fa-jpy:before { + content: "\f157"; +} +.fa-ruble:before, +.fa-rouble:before, +.fa-rub:before { + content: "\f158"; +} +.fa-won:before, +.fa-krw:before { + content: "\f159"; +} +.fa-bitcoin:before, +.fa-btc:before { + content: "\f15a"; +} +.fa-file:before { + content: "\f15b"; +} +.fa-file-text:before { + content: "\f15c"; +} +.fa-sort-alpha-asc:before { + content: "\f15d"; +} +.fa-sort-alpha-desc:before { + content: "\f15e"; +} +.fa-sort-amount-asc:before { + content: "\f160"; +} +.fa-sort-amount-desc:before { + content: "\f161"; +} +.fa-sort-numeric-asc:before { + content: "\f162"; +} +.fa-sort-numeric-desc:before { + content: "\f163"; +} +.fa-thumbs-up:before { + content: "\f164"; +} +.fa-thumbs-down:before { + content: "\f165"; +} +.fa-youtube-square:before { + content: "\f166"; +} +.fa-youtube:before { + content: "\f167"; +} +.fa-xing:before { + content: "\f168"; +} +.fa-xing-square:before { + content: "\f169"; +} +.fa-youtube-play:before { + content: "\f16a"; +} +.fa-dropbox:before { + content: "\f16b"; +} +.fa-stack-overflow:before { + content: "\f16c"; +} +.fa-instagram:before { + content: "\f16d"; +} +.fa-flickr:before { + content: "\f16e"; +} +.fa-adn:before { + content: "\f170"; +} +.fa-bitbucket:before { + content: "\f171"; +} +.fa-bitbucket-square:before { + content: "\f172"; +} +.fa-tumblr:before { + content: "\f173"; +} +.fa-tumblr-square:before { + content: "\f174"; +} +.fa-long-arrow-down:before { + content: "\f175"; +} +.fa-long-arrow-up:before { + content: "\f176"; +} +.fa-long-arrow-left:before { + content: "\f177"; +} +.fa-long-arrow-right:before { + content: "\f178"; +} +.fa-apple:before { + content: "\f179"; +} +.fa-windows:before { + content: "\f17a"; +} +.fa-android:before { + content: "\f17b"; +} +.fa-linux:before { + content: "\f17c"; +} +.fa-dribbble:before { + content: "\f17d"; +} +.fa-skype:before { + content: "\f17e"; +} +.fa-foursquare:before { + content: "\f180"; +} +.fa-trello:before { + content: "\f181"; +} +.fa-female:before { + content: "\f182"; +} +.fa-male:before { + content: "\f183"; +} +.fa-gittip:before, +.fa-gratipay:before { + content: "\f184"; +} +.fa-sun-o:before { + content: "\f185"; +} +.fa-moon-o:before { + content: "\f186"; +} +.fa-archive:before { + content: "\f187"; +} +.fa-bug:before { + content: "\f188"; +} +.fa-vk:before { + content: "\f189"; +} +.fa-weibo:before { + content: "\f18a"; +} +.fa-renren:before { + content: "\f18b"; +} +.fa-pagelines:before { + content: "\f18c"; +} +.fa-stack-exchange:before { + content: "\f18d"; +} +.fa-arrow-circle-o-right:before { + content: "\f18e"; +} +.fa-arrow-circle-o-left:before { + content: "\f190"; +} +.fa-toggle-left:before, +.fa-caret-square-o-left:before { + content: "\f191"; +} +.fa-dot-circle-o:before { + content: "\f192"; +} +.fa-wheelchair:before { + content: "\f193"; +} +.fa-vimeo-square:before { + content: "\f194"; +} +.fa-turkish-lira:before, +.fa-try:before { + content: "\f195"; +} +.fa-plus-square-o:before { + content: "\f196"; +} +.fa-space-shuttle:before { + content: "\f197"; +} +.fa-slack:before { + content: "\f198"; +} +.fa-envelope-square:before { + content: "\f199"; +} +.fa-wordpress:before { + content: "\f19a"; +} +.fa-openid:before { + content: "\f19b"; +} +.fa-institution:before, +.fa-bank:before, +.fa-university:before { + content: "\f19c"; +} +.fa-mortar-board:before, +.fa-graduation-cap:before { + content: "\f19d"; +} +.fa-yahoo:before { + content: "\f19e"; +} +.fa-google:before { + content: "\f1a0"; +} +.fa-reddit:before { + content: "\f1a1"; +} +.fa-reddit-square:before { + content: "\f1a2"; +} +.fa-stumbleupon-circle:before { + content: "\f1a3"; +} +.fa-stumbleupon:before { + content: "\f1a4"; +} +.fa-delicious:before { + content: "\f1a5"; +} +.fa-digg:before { + content: "\f1a6"; +} +.fa-pied-piper-pp:before { + content: "\f1a7"; +} +.fa-pied-piper-alt:before { + content: "\f1a8"; +} +.fa-drupal:before { + content: "\f1a9"; +} +.fa-joomla:before { + content: "\f1aa"; +} +.fa-language:before { + content: "\f1ab"; +} +.fa-fax:before { + content: "\f1ac"; +} +.fa-building:before { + content: "\f1ad"; +} +.fa-child:before { + content: "\f1ae"; +} +.fa-paw:before { + content: "\f1b0"; +} +.fa-spoon:before { + content: "\f1b1"; +} +.fa-cube:before { + content: "\f1b2"; +} +.fa-cubes:before { + content: "\f1b3"; +} +.fa-behance:before { + content: "\f1b4"; +} +.fa-behance-square:before { + content: "\f1b5"; +} +.fa-steam:before { + content: "\f1b6"; +} +.fa-steam-square:before { + content: "\f1b7"; +} +.fa-recycle:before { + content: "\f1b8"; +} +.fa-automobile:before, +.fa-car:before { + content: "\f1b9"; +} +.fa-cab:before, +.fa-taxi:before { + content: "\f1ba"; +} +.fa-tree:before { + content: "\f1bb"; +} +.fa-spotify:before { + content: "\f1bc"; +} +.fa-deviantart:before { + content: "\f1bd"; +} +.fa-soundcloud:before { + content: "\f1be"; +} +.fa-database:before { + content: "\f1c0"; +} +.fa-file-pdf-o:before { + content: "\f1c1"; +} +.fa-file-word-o:before { + content: "\f1c2"; +} +.fa-file-excel-o:before { + content: "\f1c3"; +} +.fa-file-powerpoint-o:before { + content: "\f1c4"; +} +.fa-file-photo-o:before, +.fa-file-picture-o:before, +.fa-file-image-o:before { + content: "\f1c5"; +} +.fa-file-zip-o:before, +.fa-file-archive-o:before { + content: "\f1c6"; +} +.fa-file-sound-o:before, +.fa-file-audio-o:before { + content: "\f1c7"; +} +.fa-file-movie-o:before, +.fa-file-video-o:before { + content: "\f1c8"; +} +.fa-file-code-o:before { + content: "\f1c9"; +} +.fa-vine:before { + content: "\f1ca"; +} +.fa-codepen:before { + content: "\f1cb"; +} +.fa-jsfiddle:before { + content: "\f1cc"; +} +.fa-life-bouy:before, +.fa-life-buoy:before, +.fa-life-saver:before, +.fa-support:before, +.fa-life-ring:before { + content: "\f1cd"; +} +.fa-circle-o-notch:before { + content: "\f1ce"; +} +.fa-ra:before, +.fa-resistance:before, +.fa-rebel:before { + content: "\f1d0"; +} +.fa-ge:before, +.fa-empire:before { + content: "\f1d1"; +} +.fa-git-square:before { + content: "\f1d2"; +} +.fa-git:before { + content: "\f1d3"; +} +.fa-y-combinator-square:before, +.fa-yc-square:before, +.fa-hacker-news:before { + content: "\f1d4"; +} +.fa-tencent-weibo:before { + content: "\f1d5"; +} +.fa-qq:before { + content: "\f1d6"; +} +.fa-wechat:before, +.fa-weixin:before { + content: "\f1d7"; +} +.fa-send:before, +.fa-paper-plane:before { + content: "\f1d8"; +} +.fa-send-o:before, +.fa-paper-plane-o:before { + content: "\f1d9"; +} +.fa-history:before { + content: "\f1da"; +} +.fa-circle-thin:before { + content: "\f1db"; +} +.fa-header:before { + content: "\f1dc"; +} +.fa-paragraph:before { + content: "\f1dd"; +} +.fa-sliders:before { + content: "\f1de"; +} +.fa-share-alt:before { + content: "\f1e0"; +} +.fa-share-alt-square:before { + content: "\f1e1"; +} +.fa-bomb:before { + content: "\f1e2"; +} +.fa-soccer-ball-o:before, +.fa-futbol-o:before { + content: "\f1e3"; +} +.fa-tty:before { + content: "\f1e4"; +} +.fa-binoculars:before { + content: "\f1e5"; +} +.fa-plug:before { + content: "\f1e6"; +} +.fa-slideshare:before { + content: "\f1e7"; +} +.fa-twitch:before { + content: "\f1e8"; +} +.fa-yelp:before { + content: "\f1e9"; +} +.fa-newspaper-o:before { + content: "\f1ea"; +} +.fa-wifi:before { + content: "\f1eb"; +} +.fa-calculator:before { + content: "\f1ec"; +} +.fa-paypal:before { + content: "\f1ed"; +} +.fa-google-wallet:before { + content: "\f1ee"; +} +.fa-cc-visa:before { + content: "\f1f0"; +} +.fa-cc-mastercard:before { + content: "\f1f1"; +} +.fa-cc-discover:before { + content: "\f1f2"; +} +.fa-cc-amex:before { + content: "\f1f3"; +} +.fa-cc-paypal:before { + content: "\f1f4"; +} +.fa-cc-stripe:before { + content: "\f1f5"; +} +.fa-bell-slash:before { + content: "\f1f6"; +} +.fa-bell-slash-o:before { + content: "\f1f7"; +} +.fa-trash:before { + content: "\f1f8"; +} +.fa-copyright:before { + content: "\f1f9"; +} +.fa-at:before { + content: "\f1fa"; +} +.fa-eyedropper:before { + content: "\f1fb"; +} +.fa-paint-brush:before { + content: "\f1fc"; +} +.fa-birthday-cake:before { + content: "\f1fd"; +} +.fa-area-chart:before { + content: "\f1fe"; +} +.fa-pie-chart:before { + content: "\f200"; +} +.fa-line-chart:before { + content: "\f201"; +} +.fa-lastfm:before { + content: "\f202"; +} +.fa-lastfm-square:before { + content: "\f203"; +} +.fa-toggle-off:before { + content: "\f204"; +} +.fa-toggle-on:before { + content: "\f205"; +} +.fa-bicycle:before { + content: "\f206"; +} +.fa-bus:before { + content: "\f207"; +} +.fa-ioxhost:before { + content: "\f208"; +} +.fa-angellist:before { + content: "\f209"; +} +.fa-cc:before { + content: "\f20a"; +} +.fa-shekel:before, +.fa-sheqel:before, +.fa-ils:before { + content: "\f20b"; +} +.fa-meanpath:before { + content: "\f20c"; +} +.fa-buysellads:before { + content: "\f20d"; +} +.fa-connectdevelop:before { + content: "\f20e"; +} +.fa-dashcube:before { + content: "\f210"; +} +.fa-forumbee:before { + content: "\f211"; +} +.fa-leanpub:before { + content: "\f212"; +} +.fa-sellsy:before { + content: "\f213"; +} +.fa-shirtsinbulk:before { + content: "\f214"; +} +.fa-simplybuilt:before { + content: "\f215"; +} +.fa-skyatlas:before { + content: "\f216"; +} +.fa-cart-plus:before { + content: "\f217"; +} +.fa-cart-arrow-down:before { + content: "\f218"; +} +.fa-diamond:before { + content: "\f219"; +} +.fa-ship:before { + content: "\f21a"; +} +.fa-user-secret:before { + content: "\f21b"; +} +.fa-motorcycle:before { + content: "\f21c"; +} +.fa-street-view:before { + content: "\f21d"; +} +.fa-heartbeat:before { + content: "\f21e"; +} +.fa-venus:before { + content: "\f221"; +} +.fa-mars:before { + content: "\f222"; +} +.fa-mercury:before { + content: "\f223"; +} +.fa-intersex:before, +.fa-transgender:before { + content: "\f224"; +} +.fa-transgender-alt:before { + content: "\f225"; +} +.fa-venus-double:before { + content: "\f226"; +} +.fa-mars-double:before { + content: "\f227"; +} +.fa-venus-mars:before { + content: "\f228"; +} +.fa-mars-stroke:before { + content: "\f229"; +} +.fa-mars-stroke-v:before { + content: "\f22a"; +} +.fa-mars-stroke-h:before { + content: "\f22b"; +} +.fa-neuter:before { + content: "\f22c"; +} +.fa-genderless:before { + content: "\f22d"; +} +.fa-facebook-official:before { + content: "\f230"; +} +.fa-pinterest-p:before { + content: "\f231"; +} +.fa-whatsapp:before { + content: "\f232"; +} +.fa-server:before { + content: "\f233"; +} +.fa-user-plus:before { + content: "\f234"; +} +.fa-user-times:before { + content: "\f235"; +} +.fa-hotel:before, +.fa-bed:before { + content: "\f236"; +} +.fa-viacoin:before { + content: "\f237"; +} +.fa-train:before { + content: "\f238"; +} +.fa-subway:before { + content: "\f239"; +} +.fa-medium:before { + content: "\f23a"; +} +.fa-yc:before, +.fa-y-combinator:before { + content: "\f23b"; +} +.fa-optin-monster:before { + content: "\f23c"; +} +.fa-opencart:before { + content: "\f23d"; +} +.fa-expeditedssl:before { + content: "\f23e"; +} +.fa-battery-4:before, +.fa-battery:before, +.fa-battery-full:before { + content: "\f240"; +} +.fa-battery-3:before, +.fa-battery-three-quarters:before { + content: "\f241"; +} +.fa-battery-2:before, +.fa-battery-half:before { + content: "\f242"; +} +.fa-battery-1:before, +.fa-battery-quarter:before { + content: "\f243"; +} +.fa-battery-0:before, +.fa-battery-empty:before { + content: "\f244"; +} +.fa-mouse-pointer:before { + content: "\f245"; +} +.fa-i-cursor:before { + content: "\f246"; +} +.fa-object-group:before { + content: "\f247"; +} +.fa-object-ungroup:before { + content: "\f248"; +} +.fa-sticky-note:before { + content: "\f249"; +} +.fa-sticky-note-o:before { + content: "\f24a"; +} +.fa-cc-jcb:before { + content: "\f24b"; +} +.fa-cc-diners-club:before { + content: "\f24c"; +} +.fa-clone:before { + content: "\f24d"; +} +.fa-balance-scale:before { + content: "\f24e"; +} +.fa-hourglass-o:before { + content: "\f250"; +} +.fa-hourglass-1:before, +.fa-hourglass-start:before { + content: "\f251"; +} +.fa-hourglass-2:before, +.fa-hourglass-half:before { + content: "\f252"; +} +.fa-hourglass-3:before, +.fa-hourglass-end:before { + content: "\f253"; +} +.fa-hourglass:before { + content: "\f254"; +} +.fa-hand-grab-o:before, +.fa-hand-rock-o:before { + content: "\f255"; +} +.fa-hand-stop-o:before, +.fa-hand-paper-o:before { + content: "\f256"; +} +.fa-hand-scissors-o:before { + content: "\f257"; +} +.fa-hand-lizard-o:before { + content: "\f258"; +} +.fa-hand-spock-o:before { + content: "\f259"; +} +.fa-hand-pointer-o:before { + content: "\f25a"; +} +.fa-hand-peace-o:before { + content: "\f25b"; +} +.fa-trademark:before { + content: "\f25c"; +} +.fa-registered:before { + content: "\f25d"; +} +.fa-creative-commons:before { + content: "\f25e"; +} +.fa-gg:before { + content: "\f260"; +} +.fa-gg-circle:before { + content: "\f261"; +} +.fa-tripadvisor:before { + content: "\f262"; +} +.fa-odnoklassniki:before { + content: "\f263"; +} +.fa-odnoklassniki-square:before { + content: "\f264"; +} +.fa-get-pocket:before { + content: "\f265"; +} +.fa-wikipedia-w:before { + content: "\f266"; +} +.fa-safari:before { + content: "\f267"; +} +.fa-chrome:before { + content: "\f268"; +} +.fa-firefox:before { + content: "\f269"; +} +.fa-opera:before { + content: "\f26a"; +} +.fa-internet-explorer:before { + content: "\f26b"; +} +.fa-tv:before, +.fa-television:before { + content: "\f26c"; +} +.fa-contao:before { + content: "\f26d"; +} +.fa-500px:before { + content: "\f26e"; +} +.fa-amazon:before { + content: "\f270"; +} +.fa-calendar-plus-o:before { + content: "\f271"; +} +.fa-calendar-minus-o:before { + content: "\f272"; +} +.fa-calendar-times-o:before { + content: "\f273"; +} +.fa-calendar-check-o:before { + content: "\f274"; +} +.fa-industry:before { + content: "\f275"; +} +.fa-map-pin:before { + content: "\f276"; +} +.fa-map-signs:before { + content: "\f277"; +} +.fa-map-o:before { + content: "\f278"; +} +.fa-map:before { + content: "\f279"; +} +.fa-commenting:before { + content: "\f27a"; +} +.fa-commenting-o:before { + content: "\f27b"; +} +.fa-houzz:before { + content: "\f27c"; +} +.fa-vimeo:before { + content: "\f27d"; +} +.fa-black-tie:before { + content: "\f27e"; +} +.fa-fonticons:before { + content: "\f280"; +} +.fa-reddit-alien:before { + content: "\f281"; +} +.fa-edge:before { + content: "\f282"; +} +.fa-credit-card-alt:before { + content: "\f283"; +} +.fa-codiepie:before { + content: "\f284"; +} +.fa-modx:before { + content: "\f285"; +} +.fa-fort-awesome:before { + content: "\f286"; +} +.fa-usb:before { + content: "\f287"; +} +.fa-product-hunt:before { + content: "\f288"; +} +.fa-mixcloud:before { + content: "\f289"; +} +.fa-scribd:before { + content: "\f28a"; +} +.fa-pause-circle:before { + content: "\f28b"; +} +.fa-pause-circle-o:before { + content: "\f28c"; +} +.fa-stop-circle:before { + content: "\f28d"; +} +.fa-stop-circle-o:before { + content: "\f28e"; +} +.fa-shopping-bag:before { + content: "\f290"; +} +.fa-shopping-basket:before { + content: "\f291"; +} +.fa-hashtag:before { + content: "\f292"; +} +.fa-bluetooth:before { + content: "\f293"; +} +.fa-bluetooth-b:before { + content: "\f294"; +} +.fa-percent:before { + content: "\f295"; +} +.fa-gitlab:before { + content: "\f296"; +} +.fa-wpbeginner:before { + content: "\f297"; +} +.fa-wpforms:before { + content: "\f298"; +} +.fa-envira:before { + content: "\f299"; +} +.fa-universal-access:before { + content: "\f29a"; +} +.fa-wheelchair-alt:before { + content: "\f29b"; +} +.fa-question-circle-o:before { + content: "\f29c"; +} +.fa-blind:before { + content: "\f29d"; +} +.fa-audio-description:before { + content: "\f29e"; +} +.fa-volume-control-phone:before { + content: "\f2a0"; +} +.fa-braille:before { + content: "\f2a1"; +} +.fa-assistive-listening-systems:before { + content: "\f2a2"; +} +.fa-asl-interpreting:before, +.fa-american-sign-language-interpreting:before { + content: "\f2a3"; +} +.fa-deafness:before, +.fa-hard-of-hearing:before, +.fa-deaf:before { + content: "\f2a4"; +} +.fa-glide:before { + content: "\f2a5"; +} +.fa-glide-g:before { + content: "\f2a6"; +} +.fa-signing:before, +.fa-sign-language:before { + content: "\f2a7"; +} +.fa-low-vision:before { + content: "\f2a8"; +} +.fa-viadeo:before { + content: "\f2a9"; +} +.fa-viadeo-square:before { + content: "\f2aa"; +} +.fa-snapchat:before { + content: "\f2ab"; +} +.fa-snapchat-ghost:before { + content: "\f2ac"; +} +.fa-snapchat-square:before { + content: "\f2ad"; +} +.fa-pied-piper:before { + content: "\f2ae"; +} +.fa-first-order:before { + content: "\f2b0"; +} +.fa-yoast:before { + content: "\f2b1"; +} +.fa-themeisle:before { + content: "\f2b2"; +} +.fa-google-plus-circle:before, +.fa-google-plus-official:before { + content: "\f2b3"; +} +.fa-fa:before, +.fa-font-awesome:before { + content: "\f2b4"; +} +.fa-handshake-o:before { + content: "\f2b5"; +} +.fa-envelope-open:before { + content: "\f2b6"; +} +.fa-envelope-open-o:before { + content: "\f2b7"; +} +.fa-linode:before { + content: "\f2b8"; +} +.fa-address-book:before { + content: "\f2b9"; +} +.fa-address-book-o:before { + content: "\f2ba"; +} +.fa-vcard:before, +.fa-address-card:before { + content: "\f2bb"; +} +.fa-vcard-o:before, +.fa-address-card-o:before { + content: "\f2bc"; +} +.fa-user-circle:before { + content: "\f2bd"; +} +.fa-user-circle-o:before { + content: "\f2be"; +} +.fa-user-o:before { + content: "\f2c0"; +} +.fa-id-badge:before { + content: "\f2c1"; +} +.fa-drivers-license:before, +.fa-id-card:before { + content: "\f2c2"; +} +.fa-drivers-license-o:before, +.fa-id-card-o:before { + content: "\f2c3"; +} +.fa-quora:before { + content: "\f2c4"; +} +.fa-free-code-camp:before { + content: "\f2c5"; +} +.fa-telegram:before { + content: "\f2c6"; +} +.fa-thermometer-4:before, +.fa-thermometer:before, +.fa-thermometer-full:before { + content: "\f2c7"; +} +.fa-thermometer-3:before, +.fa-thermometer-three-quarters:before { + content: "\f2c8"; +} +.fa-thermometer-2:before, +.fa-thermometer-half:before { + content: "\f2c9"; +} +.fa-thermometer-1:before, +.fa-thermometer-quarter:before { + content: "\f2ca"; +} +.fa-thermometer-0:before, +.fa-thermometer-empty:before { + content: "\f2cb"; +} +.fa-shower:before { + content: "\f2cc"; +} +.fa-bathtub:before, +.fa-s15:before, +.fa-bath:before { + content: "\f2cd"; +} +.fa-podcast:before { + content: "\f2ce"; +} +.fa-window-maximize:before { + content: "\f2d0"; +} +.fa-window-minimize:before { + content: "\f2d1"; +} +.fa-window-restore:before { + content: "\f2d2"; +} +.fa-times-rectangle:before, +.fa-window-close:before { + content: "\f2d3"; +} +.fa-times-rectangle-o:before, +.fa-window-close-o:before { + content: "\f2d4"; +} +.fa-bandcamp:before { + content: "\f2d5"; +} +.fa-grav:before { + content: "\f2d6"; +} +.fa-etsy:before { + content: "\f2d7"; +} +.fa-imdb:before { + content: "\f2d8"; +} +.fa-ravelry:before { + content: "\f2d9"; +} +.fa-eercast:before { + content: "\f2da"; +} +.fa-microchip:before { + content: "\f2db"; +} +.fa-snowflake-o:before { + content: "\f2dc"; +} +.fa-superpowers:before { + content: "\f2dd"; +} +.fa-wpexplorer:before { + content: "\f2de"; +} +.fa-meetup:before { + content: "\f2e0"; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} diff --git a/docs/v4/css/site.css b/docs/v4/css/site.css new file mode 100644 index 0000000..1e66082 --- /dev/null +++ b/docs/v4/css/site.css @@ -0,0 +1,7 @@ +/* + +Source Available at https://github.com/spring-io/asciidoctor-spring-backend */ + + +:root{--html-font-size:1em;--pixel-to-rem:16 * 1rem;--font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";--font-weight:400;--monospace-font-family:"SFMono-Regular","Consolas","Liberation Mono","Menlo",monospace;--body-background-color:#fff;--panel-background-color:#f6f8fa;--panel-group-background-color:#e1e8e8;--panel-border-color:#eaedf0;--color-accent-1:#ebf2f2;--color-accent-2:#d7e7e7;--color-accent-3:#6db33f;--body-font-color:#191e1e;--body-font-light-color:#273030;--body-font-dark-color:#141818;--link-font-color:#1565c0;--hover-link-font-color:#104d92;--scrollbar-thumb-color:silver;--mark-background-color:#39ff14;--selected-background-color:#191e1e;--layout-banner-logo-offset:18px;--layout-banner-logo-height:50px;--layout-max-width:1400px;--layout-banner-height:80px;--layout-border-color:var(--color-accent-1);--layout-switchtheme-invert-filter:invert();--layout-switchtheme-background-color:var(--body-background-color);--layout-switchtheme-button-color:var(--body-background-color);--layout-switchtheme-button-hover-color:var(--color-accent-1);--asciidoctor-doc-embellishment-margin-width:250px;--asciidoctor-doc-background-embellishment-height:147px;--asciidoctor-details-background:var(--color-accent-1);--asciidoctor-details-font-color:var(--body-font-light-color);--asciidoctor-author-separator-color:var(--color-accent-3);--asciidoctor-panel-background:var(--panel-background-color);--asciidoctor-panel-border-color:var(--panel-border-color);--asciidoctor-font-color:var(--body-font-color);--asciidoctor-heading-font-color:var(--body-font-dark-color);--asciidoctor-heading-font-weight:600;--asciidoctor-alt-heading-font-weight:600;--asciidoctor-section-divider-color:var(--color-accent-1);--asciidoctor-link-font-color:var(--link-font-color);--asciidoctor-hover-link-font-color:var(--hover-link-font-color);--asciidoctor-unresolved-link-font-color:#d32f2f;--asciidoctor-code-font-color:var(--asciidoctor-font-color);--asciidoctor-code-link-font-color:var(--link-font-color);--asciidoctor-code-background:rgba(27,31,35,.05);--asciidoctor-code-data-lang-color:#999;--asciidoctor-table-border-color:var(--asciidoctor-panel-border-color);--asciidoctor-table-header-footer-background:var(--color-accent-1);--asciidoctor-table-stripe-background:var(--color-accent-1);--asciidoctor-table-footer-background:linear-gradient(to bottom,var(--color-accent-1) 0%,var(--body-background-color) 100%);--asciidoctor-admonition-background:var(--color-accent-1);--asciidoctor-admonition-pre-background:var(--color-accent-2);--asciidoctor-admonition-label-font-weight:500;--asciidoctor-admonition-font-color:#f0f0f0;--asciidoctor-admonition-caution-background:#561164;--asciidoctor-admonition-important-background:#960000;--asciidoctor-admonition-note-background:#015785;--asciidoctor-admonition-tip-background:#3e6b1f;--asciidoctor-admonition-warning-background:#bd7400;--asciidoctor-abstract-background:var(--asciidoctor-panel-background);--asciidoctor-abstract-border-color:var(--asciidoctor-panel-border-color);--asciidoctor-quote-background:var(--color-accent-1);--asciidoctor-quote-border-color:var(--color-accent-3);--asciidoctor-quote-attribution-font-color:var(--color-accent-3);--asciidoctor-caption-font-color:var(--body-font-light-color);--asciidoctor-caption-font-weight:400;--asciidoctor-example-background:var(--asciidoctor-panel-background);--asciidoctor-example-border-color:var(--asciidoctor-panel-border-color);--asciidoctor-sidebar-background:var(--color-accent-1);--asciidoctor-pre-background:var(--asciidoctor-panel-background);--asciidoctor-pre-border-color:var(--asciidoctor-panel-border-color);--asciidoctor-callout-background:var(--body-font-dark-color);--asciidoctor-callout-font-color:var(--body-background-color);--asciidoctor-footer-font-color:#b6b6b6;--highlight-background-color:var(--asciidoctor-pre-background);--highlight-font-color:#24292e;--highlight-keyword-font-color:#d73a49;--highlight-comment-font-color:#6a737d;--highlight-string-font-color:#032f62;--highlight-meta-font-color:#6a737d;--highlight-constant-font-color:#032f62;--highlight-variable-font-color:#005cc5;--highlight-tag-font-color:#22863a;--highlight-tag-attribute-font-color:#6f42c1;--highlight-type-font-color:#6f42c1;--highlight-link-font-color:var(--link-font-color);--highlight-addition-font-color:#22863a;--highlight-deletion-font-color:#24292e;--highlight-regex-font-color:#032f62;--tabs-border-color:var(--selected-background-color);--tabs-background-color:var(--body-background-color);--tabs-font-color:var(--body-font-color);--tabs-selected-background-color:var(--selected-background-color);--tabs-selected-font-color:var(--body-background-color);--tabs-hover-font-color:var(--hover-link-font-color);--tabs-hover-background:var(--color-accent-1);--tabs-group-background-color:var(--panel-group-background-color);--toc-width:24rem;--toc-display:block;--toc-font-color:var(--body-font-color);--toc-hover-background-color:var(--color-accent-1);--toc-active-background-color:var(--selected-background-color);--toc-active-font-color:var(--body-background-color);--toc-back-to-index-filter:none;--toc-bar-display:none;--toc-bar-height:0;--toc-bar-button-filter:none;--codetools-button-filter:none;--codetools-button-active-filter:invert();--codetools-background-color:var(--body-background-color);--codetools-border-color:rgba(0,0,0,.3);--codetools-hover-background-color:var(--color-accent-1);--codetools-divider-color:var(--codetools-border-color);--codetools-popup-background-color:var(--selected-background-color);--codetools-popup-font-color:var(--body-background-color)}@media screen and (max-width:1024px){:root{--toc-width:16rem;--asciidoctor-doc-embellishment-margin-width:140px}}@media screen and (max-width:800px){:root{--layout-banner-height:51px;--layout-banner-logo-height:30px;--layout-banner-logo-offset:10px;--layout-border-color:var(--body-background-color);--toc-bar-display:block;--toc-bar-height:24px;--toc-width:0;--toc-display:none;--asciidoctor-doc-embellishment-margin-width:0}}html.dark-theme{--font-weight:300;--body-background-color:#1b1f23;--panel-background-color:#262a2d;--panel-group-background-color:#303741;--panel-border-color:#2c3135;--color-accent-1:#272c33;--color-accent-1-invert:#d8d3cc;--color-accent-2:#2d333a;--color-accent-3:#6db33f;--body-font-color:#bbbcbe;--body-font-light-color:#abacaf;--body-font-dark-color:#cecfd1;--link-font-color:#086dc3;--hover-link-font-color:#107ddd;--scrollbar-thumb-color:#5f5f5f;--mark-background-color:#2eca12;--selected-background-color:#8d8d8d;--layout-switchtheme-invert-filter:none;--layout-switchtheme-background-color:var(--selected-background-color);--asciidoctor-code-background:rgba(177,209,241,.15);--asciidoctor-code-data-lang-color:#6e6e6e;--asciidoctor-admonition-font-color:#f0f0f0;--asciidoctor-admonition-caution-background:#603668;--asciidoctor-admonition-important-background:#924040;--asciidoctor-admonition-note-background:#355463;--asciidoctor-admonition-tip-background:#4d6340;--asciidoctor-admonition-warning-background:#967745;--asciidoctor-footer-font-color:#5e5e5e;--highlight-background-color:var(--asciidoctor-pre-background);--highlight-font-color:#f6f8fa;--highlight-keyword-font-color:#ea4a5a;--highlight-comment-font-color:#959da5;--highlight-string-font-color:#79b8ff;--highlight-meta-font-color:#959da5;--highlight-constant-font-color:#79b8ff;--highlight-variable-font-color:#c8e1ff;--highlight-tag-font-color:#7bcc72;--highlight-tag-attribute-font-color:#b392f0;--highlight-type-font-color:#b392f0;--highlight-link-font-color:#1565c0;--highlight-addition-font-color:#7bcc72;--highlight-deletion-font-color:#f6f8fa;--highlight-regex-font-color:#79b8ff;--toc-back-to-index-filter:invert();--toc-bar-button-filter:invert();--codetools-button-filter:invert();--codetools-button-active-filter:none;--codetools-hover-background-color:var(--color-accent-1-invert);--codetools-border-color:hsla(0,0%,100%,.274);--codetools-divider-color:rgba(44,44,44,.274)}html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}body{-webkit-text-size-adjust:none;-moz-text-size-adjust:none;text-size-adjust:none}html{font-size:var(--html-font-size);height:100%;min-width:340px;scroll-behavior:smooth}body{background-color:var(--body-background-color);color:var(--body-font-color);font-family:var(--font-family);font-weight:var(--font-weight);margin:0;overflow-wrap:anywhere;overscroll-behavior:none}a{text-decoration:none}a:hover{text-decoration:underline}a:active{background-color:none}code,kbd,pre{font-family:var(--monospace-font-family)}@supports (scrollbar-width:thin){body *{scrollbar-color:var(--scrollbar-thumb-color) transparent;scrollbar-width:thin}}table{word-wrap:normal;border-collapse:collapse}mark{background:var(--mark-background-color)}#banner-container{border-bottom:1px solid var(--layout-border-color);height:var(--layout-banner-height);overflow:hidden}#banner{background:no-repeat top var(--layout-banner-logo-offset) left var(--layout-banner-logo-offset) /auto var(--layout-banner-logo-height);background-image:url(../img/banner-logo.svg);height:100%}#doc{overflow:auto}.contained{margin:0 auto;max-width:var(--layout-max-width)}#switch-theme label,div#switch-theme{display:none}html.js div#switch-theme{display:block;float:right;margin:8px 6px 0 0}#switch-theme input{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:no-repeat url(../img/octicons-16.svg#view-sun) 90% 50%/16px 16px,no-repeat url(../img/octicons-16.svg#view-moon) 10% 50%/16px 16px;background-color:var(--layout-switchtheme-background-color);height:22px;outline:none;position:relative;width:40px}#switch-theme input,#switch-theme input:before{border-radius:25px;filter:var(--layout-switchtheme-invert-filter)}#switch-theme input:before{background-color:var(--layout-switchtheme-button-color);content:"";height:18px;left:2px;position:absolute;top:2px;transition:transform .2s;width:18px}#switch-theme:hover input:before{background-color:var(--layout-switchtheme-button-hover-color)}#switch-theme input:checked:before{transform:translateX(18px)}.doc{color:var(--asciidoctor-font-color);-webkit-hyphens:none;hyphens:none;letter-spacing:-.0027777778rem;line-height:1.6;margin:0}.doc #content,.doc #footer{margin:0 2rem}.doc #header>:not(#toc){margin-left:2rem;margin-right:2rem}.doc #content{padding-bottom:4rem}#doc{background:no-repeat 100% 0/305px 147px;background-image:url(../img/doc-background.svg)}.doc #header{margin-right:var(--asciidoctor-doc-embellishment-margin-width)}.doc #header .details{background:var(--asciidoctor-details-background);color:var(--asciidoctor-details-font-color);font-size:.8em;font-weight:600;padding:1rem 1.5rem}.doc #header div.details{display:flex;flex-wrap:wrap}#header .details br{display:none}.doc #header .details span.author:not(:last-of-type):after{color:var(--asciidoctor-author-separator-color);content:"\2022";font-weight:400;margin:.4em}.doc #header .details span.last-author:after{display:none}.doc #header .details #revnumber{flex-basis:100%;font-weight:200;margin-top:.5rem;text-transform:capitalize}.doc #preamble+.sect1,.doc .sect1+.sect1{margin-top:2rem}.doc .sect1+.sect1{border-top:1px solid var(--asciidoctor-section-divider-color)}.doc h1{font-size:2.3em}.doc h2{font-size:2em}.doc h3{font-size:1.7em}.doc h4{font-size:1.6em}.doc h5{font-size:1.4em}.doc h6{font-size:1.3em}.doc h1,.doc h2,.doc h3,.doc h4,.doc h5,.doc h6{color:var(--asciidoctor-heading-font-color);font-weight:var(--asciidoctor-heading-font-weight);-webkit-hyphens:none;hyphens:none;line-height:1.3;margin:1.3rem 0 0;padding-top:1.8rem}.doc h1.sect0{background:var(--asciidoctor-abstract-background);font-size:1.8em;margin:1.5rem -1rem 0;padding:.5rem 1rem}.doc h1:first-child{margin:1.3rem 0}.doc h2:not(.discrete){margin-left:-1rem;margin-right:-1rem;padding:1.8rem 1rem .1rem}.doc h3:not(.discrete){font-weight:var(--asciidoctor-alt-heading-font-weight)}.doc h1 .anchor,.doc h2 .anchor,.doc h3 .anchor,.doc h4 .anchor,.doc h5 .anchor,.doc h6 .anchor{font-weight:400;margin-left:-2ex;padding-left:.5ex;position:absolute;text-decoration:none;visibility:hidden;width:2.25ex}.doc h1 .anchor:before,.doc h2 .anchor:before,.doc h3 .anchor:before,.doc h4 .anchor:before,.doc h5 .anchor:before,.doc h6 .anchor:before{content:"\0023"}.doc h1:hover .anchor,.doc h2:hover .anchor,.doc h3:hover .anchor,.doc h4:hover .anchor,.doc h5:hover .anchor,.doc h6:hover .anchor{visibility:visible}.doc dl,.doc p{margin:0}.doc a.bare{-webkit-hyphens:none;hyphens:none}.doc a{color:var(--asciidoctor-link-font-color)}.doc a:hover{color:var(--asciidoctor-hover-link-font-color)}.doc a.unresolved{color:var(--asciidoctor-unresolved-link-font-color)}.doc .admonitionblock code,.doc p code,.doc thead code{background:var(--asciidoctor-code-background);border-radius:.25em;color:var(--asciidoctor-code-font-color);font-size:.95em;padding:.125em .25em}.doc .admonitionblock a code,.doc p a code,.doc thead a code{color:var(--asciidoctor-code-link-font-color)}.doc code,.doc pre{-webkit-hyphens:none;hyphens:none}.doc pre{font-size:calc(14/var(--pixel-to-rem));line-height:1.3;margin:0}.doc .listingblock pre:not(.highlight),.doc .literalblock pre,.doc pre.highlight code{background:var(--asciidoctor-pre-background);border-radius:4px;box-shadow:inset 0 0 1.75px var(--asciidoctor-pre-border-color);display:block;overflow-x:auto;padding:.95rem}.doc pre.highlight code[data-lang]:before{color:var(--asciidoctor-code-data-lang-color);content:attr(data-lang);display:block;font-size:.65em;line-height:1;position:absolute;right:.3rem;text-transform:uppercase;top:.3rem}.doc pre.highlight{position:relative}.doc table pre.highlight code[data-lang]:before{display:none}.doc blockquote{margin:0}.doc .paragraph.lead>p{font-size:calc(18/var(--pixel-to-rem))}.doc .dlist,.doc .exampleblock,.doc .hdlist,.doc .imageblock,.doc .listingblock,.doc .literalblock,.doc .olist,.doc .paragraph,.doc .partintro,.doc .quoteblock,.doc .sidebarblock,.doc .ulist,.doc .verseblock,.doc details,.doc hr{margin:1rem 0 0}.doc table.tableblock{display:block;overflow-x:auto;width:100%}.doc table.tableblock td{min-width:6rem}.doc table.tableblock{font-size:calc(15/var(--pixel-to-rem));margin:1.5rem 0 0}.doc table.tableblock+*{margin-top:2rem}.doc td.tableblock>.content>:first-child{margin-top:0}.doc table.tableblock td,.doc table.tableblock th{padding:.5rem}.doc table.tableblock thead th{border-bottom:2.5px solid var(--asciidoctor-table-border-color)}.doc table.tableblock td,.doc table.tableblock>:not(thead) th{border-bottom:1px solid var(--asciidoctor-table-border-color);border-top:1px solid var(--asciidoctor-table-border-color)}.doc table.stripes-all>tbody>tr,.doc table.stripes-even>tbody>tr:nth-of-type(2n),.doc table.stripes-hover>tbody>tr:hover,.doc table.stripes-odd>tbody>tr:nth-of-type(odd){background:var(--asciidoctor-table-stripe-background)}.doc table.tableblock>tfoot{background:var(--asciidoctor-table-footer-background)}.doc .listingblock.wrap pre,.doc .tableblock code,.doc .tableblock pre{white-space:pre-wrap}.doc td:first-child .listingblock.wrap pre,.doc td:first-child .tableblock code,.doc td:first-child .tableblock pre{white-space:nowrap}.doc .admonitionblock{margin:2.5rem 0}.doc .admonitionblock p,.doc .admonitionblock td.content{font-size:calc(16/var(--pixel-to-rem))}.doc .admonitionblock td.content>.title+*,.doc .admonitionblock td.content>:not(.title):first-child{margin-top:0}.doc .admonitionblock pre{border:none;font-size:calc(14/var(--pixel-to-rem))}.doc .admonitionblock>table{position:relative;table-layout:fixed;width:100%}.doc .admonitionblock td.content{word-wrap:anywhere;background:var(--asciidoctor-admonition-background);padding:1rem 1rem .75rem;width:100%}.doc .admonitionblock td.icon{border-radius:.45rem;font-size:calc(16/var(--pixel-to-rem));left:0;line-height:1;padding:.25em .075em;position:absolute;top:0;transform:translate(-.5rem,-50%)}.doc .admonitionblock .icon i{align-items:center;background-position:.5em 0;background-repeat:no-repeat;display:inline-flex;filter:invert(100%);height:16px;padding-left:2em;vertical-align:initial;width:auto}.doc .admonitionblock .icon i:after{border-left:1px solid hsla(0,0%,100%,.3);color:var(--asciidoctor-admonition-font-color);content:attr(title);filter:invert(100%);font-style:normal;font-weight:var(--asciidoctor-admonition-label-font-weight);-webkit-hyphens:none;hyphens:none;margin:-.05em;padding:0 .5em;text-transform:capitalize}i.fa{background-size:16px 16px}i.fa.icon-caution{background-image:url(../img/octicons-16.svg#view-flame)}i.fa.icon-important{background-image:url(../img/octicons-16.svg#view-stop)}i.fa.icon-note{background-image:url(../img/octicons-16.svg#view-info)}i.fa.icon-tip{background-image:url(../img/octicons-16.svg#view-light-bulb)}i.fa.icon-warning{background-image:url(../img/octicons-16.svg#view-alert)}.doc .admonitionblock.caution td.icon{background:var(--asciidoctor-admonition-caution-background)}.doc .admonitionblock.important td.icon{background:var(--asciidoctor-admonition-important-background)}.doc .admonitionblock.note .icon{background:var(--asciidoctor-admonition-note-background)}.doc .admonitionblock.tip .icon{background:var(--asciidoctor-admonition-tip-background)}.doc .admonitionblock.warning .icon{background-color:var(--asciidoctor-admonition-warning-background)}.doc .imageblock{align-items:center;display:flex;flex-direction:column}.doc .image>img,.doc .imageblock img{display:inline-block;height:auto;max-width:100%;vertical-align:middle}.doc .image:not(.left):not(.right)>img{margin-top:-.2em}.doc #preamble .abstract blockquote{background:var(--asciidoctor-abstract-background);border-left:5px solid var(--asciidoctor-abstract-border-color);font-size:calc(16/var(--pixel-to-rem));padding:.75em 1em}.doc .quoteblock,.doc .verseblock{background:var(--asciidoctor-quote-background);border-left:5px solid var(--asciidoctor-quote-border-color)}.doc .quoteblock{padding:.25rem 2rem 1.25rem}.doc .quoteblock .attribution{color:var(--asciidoctor-quote-attribution-font-color);font-size:calc(15/var(--pixel-to-rem));margin-top:.75rem}.doc .quoteblock blockquote{margin-top:1rem}.doc .quoteblock .paragraph{font-style:italic}.doc .quoteblock cite{padding-left:1em}.doc .verseblock{font-size:1.15em;padding:1rem 2rem}.doc .verseblock pre{font-family:inherit;font-size:inherit}.doc ol,.doc ul{margin:0;padding:0 0 0 2rem}.doc ol.none,.doc ol.unnumbered,.doc ol.unstyled,.doc ul.checklist,.doc ul.no-bullet,.doc ul.none,.doc ul.unstyled{list-style-type:none}.doc ol.unnumbered,.doc ul.no-bullet{padding-left:1.25rem}.doc ol.unstyled,.doc ul.unstyled{padding-left:0}.doc ul.circle,.doc ul.disc,.doc ul.square{list-style-type:square}.doc ol.arabic{list-style-type:decimal}.doc ol.decimal{list-style-type:decimal-leading-zero}.doc ol.loweralpha{list-style-type:lower-alpha}.doc ol.upperalpha{list-style-type:upper-alpha}.doc ol.lowerroman{list-style-type:lower-roman}.doc ol.upperroman{list-style-type:upper-roman}.doc ol.lowergreek{list-style-type:lower-greek}.doc ul.checklist{padding-left:.5rem}.doc ul.checklist p>i.fa-check-square-o:first-child,.doc ul.checklist p>i.fa-square-o:first-child{display:inline-flex;justify-content:center;width:1.25rem}.doc ul.checklist i.fa-check-square-o:before{content:"\2713"}.doc ul.checklist i.fa-square-o:before{content:"\274f"}.doc .dlist .dlist,.doc .dlist .olist,.doc .dlist .ulist,.doc .olist .dlist,.doc .olist .olist,.doc .olist .ulist,.doc .ulist .dlist,.doc .ulist .olist,.doc .ulist .ulist{margin-top:.5rem}.doc .olist li,.doc .ulist li{margin-bottom:.3rem}.doc .admonitionblock .listingblock,.doc .olist .listingblock,.doc .ulist .listingblock{padding:0}.doc .admonitionblock .title,.doc .exampleblock .title,.doc .imageblock .title,.doc .listingblock .title,.doc .literalblock .title,.doc .openblock .title,.doc .tableblock caption{color:var(--asciidoctor-caption-font-color);font-size:calc(14/var(--pixel-to-rem));font-style:italic;font-weight:var(--asciidoctor-caption-font-weight);-webkit-hyphens:none;hyphens:none;letter-spacing:.01em;padding-bottom:.075rem;text-align:left}.doc .imageblock .title{margin-top:.5rem;padding-bottom:0}.doc .exampleblock>.content{background:var(--asciidoctor-example-background);border:1px solid var(--asciidoctor-example-border-color);border-radius:4px;padding:.75rem}.doc .exampleblock>.content>:first-child{margin-top:0}.doc .sidebarblock{background:var(--asciidoctor-sidebar-background);padding:2.2rem}.doc .sidebarblock>.content>.title{font-size:calc(23/var(--pixel-to-rem));font-weight:var(--asciidoctor-alt-heading-font-weight);line-height:1.3;margin-bottom:1.2rem}.doc .sidebarblock>.content>:not(.title):first-child{margin-top:0}.doc b.button{white-space:nowrap}.doc b.button:before{content:"[";padding-right:.25em}.doc b.button:after{content:"]";padding-left:.25em}.doc .menuseq,.doc .path{-webkit-hyphens:none;hyphens:none}.doc .menuseq i.caret:before{content:"\203a";font-size:1.1em;font-weight:var(--asciidoctor-body-font-weight-bold);line-height:.90909}.doc kbd{background:var(--asciidoctor-kbd-background);border:1px solid var(--asciidoctor-kbd-border-color);border-radius:.25em;box-shadow:0 1px 0 var(--asciidoctor-kbd-border-color),0 0 0 .1em var(--body-background) inset;display:inline-block;font-size:calc(12/var(--pixel-to-rem));padding:.25em .5em;vertical-align:text-bottom;white-space:nowrap}.doc .keyseq,.doc kbd{line-height:1}.doc .keyseq{font-size:calc(16/var(--pixel-to-rem))}.doc .keyseq kbd{margin:0 .125em}.doc .keyseq kbd:first-child{margin-left:0}.doc .keyseq kbd:last-child{margin-right:0}.doc i.fa{font-style:normal;-webkit-hyphens:none;hyphens:none}.doc .language-console .hljs-meta{-webkit-user-select:none;-moz-user-select:none;user-select:none}.doc .dlist dt{font-style:italic}.doc .dlist dd{margin:0 0 .25rem 1.5rem}.doc .dlist dd:last-of-type{margin-bottom:0}.doc td.hdlist1,.doc td.hdlist2{padding:.5rem 0 0;vertical-align:top}.doc tr:first-child>.hdlist1,.doc tr:first-child>.hdlist2{padding-top:0}.doc td.hdlist1{font-weight:var(--body-font-weight-bold);padding-right:.25rem}.doc td.hdlist2{padding-left:.25rem}.doc .colist{font-size:calc(16/var(--pixel-to-rem));margin:.25rem 0 -.25rem}.doc .colist>table>tbody>tr>:first-child,.doc .colist>table>tr>:first-child{padding:.25em .5rem 0;vertical-align:top}.doc .colist>table>tbody>tr>:last-child,.doc .colist>table>tr>:last-child{padding:.25rem 0}.doc .conum[data-value]{background:var(--asciidoctor-callout-background);border-radius:100%;color:var(--asciidoctor-callout-font-color);display:inline-block;font-family:var(--monospace-font-family);font-size:calc(12.5/var(--pixel-to-rem));font-style:normal;height:1.25em;letter-spacing:-.25ex;line-height:1.2;text-align:center;text-indent:-.25ex;width:1.25em}.doc .conum[data-value]:after{content:attr(data-value)}.doc .conum[data-value]+b{display:none}.doc hr{border:solid var(--asciidoctor-section-divider-color);border-width:2px 0 0;height:0}.doc :not(pre).nowrap{white-space:nowrap}.doc .nobreak{word-wrap:normal;-webkit-hyphens:none;hyphens:none}.doc .right{float:right}.doc .left{float:left}.doc .stretch{width:100%}.doc .underline{text-decoration:underline}.doc .line-through{text-decoration:line-through}.doc .halign-left{text-align:left}.doc .halign-right{text-align:right}.doc .halign-center{text-align:center}.doc .valign-top{vertical-align:top}.doc .valign-bottom{vertical-align:bottom}.doc .valign-middle{vertical-align:middle}#footer #footer-text{border-top:1px solid var(--asciidoctor-section-divider-color);color:var(--asciidoctor-footer-font-color);font-size:calc(14/var(--pixel-to-rem));padding:2rem 0}html.dark-theme #doc{background:no-repeat 100% 0/305px 147px;background-image:url(../img/doc-background-dark.svg)}@media screen and (max-width:1024px){#doc{background:no-repeat 100% 0/203px 95px;background-image:url(../img/doc-background.svg)}html.dark-theme #doc{background:no-repeat 100% 0/203px 95px;background-image:url(../img/doc-background-dark.svg)}}@media screen and (max-width:800px){#doc,html.dark-theme #doc{background:none}}.hljs{background:var(--highlight-background-color);color:var(--highlight-font-color);display:block;overflow-x:auto;padding:.5em}.hljs-keyword,.hljs-selector-tag,.hljs-subst{color:var(--highlight-keyword-font-color)}.hljs-comment,.hljs-quote{color:var(--highlight-comment-font-color)}.hljs-doctag,.hljs-string{color:var(--highlight-string-font-color)}.hljs-meta{color:var(--highlight-meta-font-color)}.hljs-built_in,.hljs-builtin-name,.hljs-literal,.hljs-number,.hljs-symbol{color:var(--highlight-constant-font-color)}.hljs-template-variable,.hljs-variable{color:var(--highlight-variable-font-color)}.hljs-attribute,.hljs-name,.hljs-tag{color:var(--highlight-tag-font-color)}.hljs-tag .hljs-attr{color:var(--highlight-tag-attribute-font-color)}.hljs-class .hljs-title,.hljs-type{color:var(--highlight-type-font-color)}.hljs-regexp{color:var(--highlight-regex-font-color)}.hljs-link{color:var(--highlight-link-font-color);text-decoration:underline}.hljs-addition{color:var(--highlight-addition-font-color)}.hljs-deletion{color:var(--highlight-deletion-font-color)}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.language-json .hljs-literal,.language-json .hljs-number{color:var(--highlight-variable-font-color)}.language-json .hljs-attr{color:var(--highlight-string-font-color)}.hidden{display:none}.doc .tabs{border-style:none;bottom:0;display:inline-block;font-size:calc(12/var(--pixel-to-rem));font-weight:700;margin-bottom:calc(2/var(--pixel-to-rem));margin-top:.5rem;position:relative}.doc .tab,.doc .tab:not(:first-child){border:1px solid var(--tabs-border-color)}.doc .tab{background-color:var(--tabs-background-color);border-radius:0;color:var(--tabs-font-color);cursor:pointer;display:inline-block;margin-bottom:calc(2/var(--pixel-to-rem));padding:.3rem .6rem;transition:background-color .2s}.doc .tab:hover{background-color:var(--tabs-hover-background);color:var(--tabs-hover-font-color);text-decoration:underline}.doc .tab.selected{background-color:var(--tabs-selected-background-color);border-color:var(--tabs-selected-background-color);color:var(--tabs-selected-font-color)}.doc .tab.selected:hover{color:var(--tabs-selected-font-color);text-decoration:none}.doc div.openblock.tabs-content>.content{background-color:var(--tabs-group-background-color);padding:1rem}body.toc-left #doc{border-left:1px solid var(--layout-border-color);margin-left:var(--toc-width);overflow:auto}#toc{border-right:1px solid var(--layout-border-color);display:var(--toc-display);font-size:.95rem;line-height:1.1;margin-left:calc(var(--toc-width)*-1);padding:1.7rem 1rem 0;position:absolute;top:var(--layout-banner-height);width:var(--toc-width)}#toctitle{display:none}#toc ol,#toc ul{padding:0}#toc ul ol,#toc ul ul{padding-left:.8rem}#toc li{display:block;list-style:none}#toc a{border-radius:4px;color:var(--toc-font-color);display:block;padding:.4rem .6rem;text-decoration:none}#toc a:hover{background-color:var(--toc-hover-background-color)}body.fixed-toc #toc{height:100%;overflow-x:hidden;position:fixed;top:0}#toc li.active>a{background-color:var(--toc-active-background-color);color:var(--toc-active-font-color)}#toc>ol ol,#toc>ul ul{display:none}#toc li.active>ol,#toc li.active>ul,#toc ol.expanded,#toc ul.expanded{display:block}#back-to-index{display:block;margin-bottom:.6rem}#back-to-index a{margin-bottom:.6rem;margin-top:-.9rem;padding-left:1.6rem}#back-to-index a:before{background:no-repeat 50%/16px 16px;background-image:url(../img/octicons-16.svg#view-chevron-left);content:"";display:block;filter:var(--toc-back-to-index-filter);left:1.4rem;min-height:16px;min-width:16px;position:absolute}#tocbar-container{background-color:var(--body-background-color);border-bottom:1px solid var(--panel-border-color);display:var(--toc-bar-display);height:var(--tocbar-height);width:100%;z-index:10000}#tocbar{height:100%;padding-left:6px;width:100%}body.fixed-toc #tocbar-container{position:fixed;top:0}button#toggle-toc{background:no-repeat 50%/16px 16px;background-image:url(../img/octicons-16.svg#view-three-bars);border:none;display:block;filter:var(--toc-bar-button-filter);height:var(--toc-bar-height);outline:none;padding:0;width:var(--toc-bar-height)}body.show-toc button#toggle-toc{background-image:url(../img/octicons-16.svg#view-x)}@media screen and (max-width:800px){body.fixed-toc #toc{top:var(--toc-bar-height)}#toc{background-color:var(--body-background-color);height:100%;left:0;top:calc(var(--layout-banner-height) + var(--toc-bar-height));width:100%;z-index:10000}body.show-toc #toc{display:block}}div.codetools{--button-width:28px;--button-height:24px;--arrow-size:5px;background:var(--codetools-background-color);border:1px solid var(--codetools-border-color);border-radius:2px;bottom:9px;display:flex;opacity:0;padding:0;position:absolute;right:8px;transition:opacity .15s ease-in-out}.doc pre.highlight:hover div.codetools{opacity:1}div.codetools button{background:no-repeat 50%/16px 16px;border:none;filter:var(--codetools-button-filter);height:var(--button-height);outline:none;padding:0;width:var(--button-width)}div.codetools button:not(:last-child){border-right:1px solid var(--codetools-divider-color)}div.codetools button:hover{background-color:var(--codetools-hover-background-color);transition:filter .3s}div.codetools button:active{filter:var(--codetools-button-active-filter);transition:filter none}div.codetools button span.label{display:none}div.codetools button.copy-button{background-image:url(../img/octicons-16.svg#view-clippy)}div.codetools button.unfold-button{background-image:url(../img/octicons-16.svg#view-unfold)}div.codetools button.fold-button{background-image:url(../img/octicons-16.svg#view-fold)}div.codetools span.copied{content:"";display:block;height:var(--button-height);opacity:0;position:relative;transition:opacity .5s;width:var(--button-width);z-index:1000000}div.codetools button:active span.copied{filter:invert();transition:filter none}div.codetools span.copied:before{border:var(--arrow-size) solid var(--codetools-popup-background-color);border-color:transparent transparent var(--codetools-popup-background-color) transparent;bottom:calc(var(--arrow-size)*-1);content:"";left:50%;margin-left:calc(var(--arrow-size)/-2);position:absolute}div.codetools span.copied:after{background-color:var(--codetools-popup-background-color);border-radius:3px;color:var(--codetools-popup-font-color);content:"Copied to clipboard!";font-weight:700;margin-right:calc(var(--button-width)*-1);padding:5px 8px;position:absolute;right:100%;top:calc(var(--button-height) + var(--arrow-size))}div.codetools button.clicked span.copied{opacity:1}span.fold-block{clear:left;float:left;overflow:hidden;padding-right:.75rem;position:relative}code.unfolded span.fold-block.hide-when-folded,code:not(.unfolded) span.fold-block.hide-when-unfolded{max-height:99999px;opacity:1}code.unfolded span.fold-block.hide-when-unfolded,code:not(.unfolded) span.fold-block.hide-when-folded{max-height:0;opacity:0}code.unfolding span.fold-block.hide-when-folded{max-height:600px;opacity:1}code.folding span.fold-block.hide-when-unfolded{max-height:400px;opacity:1}code.folding span.fold-block.hide-when-folded,code.unfolding span.fold-block.hide-when-unfolded{max-height:0;opacity:0}code.unfolding span.fold-block.hide-when-unfolded{transition:max-height .2s cubic-bezier(0,1,0,1),opacity .2s linear}code.folding span.fold-block.hide-when-unfolded,code.unfolding span.fold-block.hide-when-folded{transition:max-height .2s cubic-bezier(1,0,1,0),opacity .2s linear}code.folding span.fold-block.hide-when-folded{transition:max-height .2s cubic-bezier(0,1,0,1),opacity .2s linear} +/*# sourceMappingURL=site.css.map */ diff --git a/docs/v4/css/site.css.map b/docs/v4/css/site.css.map new file mode 100644 index 0000000..da9ab69 --- /dev/null +++ b/docs/v4/css/site.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["settings.css","settings-dark.css","generic.css","elements.css","layout.css","asciidoctor.css","highlight.css","tabs.css","toc.css","codetools.css"],"names":[],"mappings":";;;;;AAgBA,MAIE,oBAAqB,CACrB,wBAAyB,CACzB,kJAEmB,CACnB,iBAAkB,CAClB,uFACoB,CACpB,4BAA8B,CAC9B,gCAAiC,CACjC,sCAAuC,CACvC,4BAA6B,CAC7B,wBAAyB,CACzB,wBAAyB,CACzB,wBAAyB,CACzB,yBAA0B,CAC1B,+BAAgC,CAChC,8BAA+B,CAC/B,yBAA0B,CAC1B,+BAAgC,CAChC,8BAA+B,CAC/B,+BAAgC,CAChC,mCAAoC,CAGpC,gCAAiC,CACjC,gCAAiC,CACjC,yBAA0B,CAC1B,2BAA4B,CAC5B,2CAA4C,CAC5C,2CAA4C,CAC5C,kEAAmE,CACnE,8DAA+D,CAC/D,6DAA8D,CAG9D,kDAAmD,CACnD,uDAAwD,CACxD,sDAAuD,CACvD,6DAA8D,CAC9D,0DAA2D,CAC3D,4DAA6D,CAC7D,0DAA2D,CAC3D,+CAAgD,CAChD,4DAA6D,CAC7D,qCAAsC,CACtC,yCAA0C,CAC1C,yDAA0D,CAC1D,oDAAqD,CACrD,gEAAiE,CACjE,gDAAiD,CACjD,2DAA4D,CAC5D,yDAA0D,CAC1D,gDAAqD,CACrD,uCAAwC,CACxC,sEAAuE,CACvE,kEAAmE,CACnE,2DAA4D,CAC5D,2HAIC,CACD,yDAA0D,CAC1D,6DAA8D,CAC9D,8CAA+C,CAC/C,2CAA4C,CAC5C,mDAAoD,CACpD,qDAAsD,CACtD,gDAAiD,CACjD,+CAAgD,CAChD,mDAAoD,CACpD,qEAAsE,CACtE,yEAA0E,CAC1E,oDAAqD,CACrD,sDAAuD,CACvD,gEAAiE,CACjE,6DAA8D,CAC9D,qCAAsC,CACtC,oEAAqE,CACrE,wEAAyE,CACzE,sDAAuD,CACvD,gEAAiE,CACjE,oEAAqE,CACrE,4DAA6D,CAC7D,6DAA8D,CAC9D,uCAAwC,CAGxC,8DAA+D,CAC/D,8BAA+B,CAC/B,sCAAuC,CACvC,sCAAuC,CACvC,qCAAsC,CACtC,mCAAoC,CACpC,uCAAwC,CACxC,uCAAwC,CACxC,kCAAmC,CACnC,4CAA6C,CAC7C,mCAAoC,CACpC,kDAAmD,CACnD,uCAAwC,CACxC,uCAAwC,CACxC,oCAAqC,CAGrC,oDAAqD,CACrD,oDAAqD,CACrD,wCAAyC,CACzC,iEAAkE,CAClE,uDAAwD,CACxD,oDAAqD,CACrD,6CAA8C,CAC9C,iEAAkE,CAGlE,iBAAkB,CAClB,mBAAoB,CACpB,uCAAwC,CACxC,kDAAmD,CACnD,8DAA+D,CAC/D,oDAAqD,CACrD,+BAAgC,CAChC,sBAAuB,CACvB,kBAAmB,CACnB,4BAA6B,CAG7B,8BAA+B,CAC/B,yCAA0C,CAC1C,yDAA0D,CAC1D,uCAA4C,CAC5C,wDAAyD,CACzD,uDAAwD,CACxD,mEAAoE,CACpE,yDACF,CAIA,qCACE,MACE,iBAAkB,CAClB,kDACF,CACF,CAEA,oCACE,MACE,2BAA4B,CAC5B,gCAAiC,CACjC,gCAAiC,CACjC,kDAAmD,CACnD,uBAAwB,CACxB,qBAAsB,CACtB,aAAc,CACd,kBAAmB,CACnB,8CACF,CACF,CCnLA,gBAEE,iBAAkB,CAClB,+BAAgC,CAChC,gCAAiC,CACjC,sCAAuC,CACvC,4BAA6B,CAC7B,wBAAyB,CACzB,+BAAgC,CAChC,wBAAyB,CACzB,wBAAyB,CACzB,yBAA0B,CAC1B,+BAAgC,CAChC,8BAA+B,CAC/B,yBAA0B,CAC1B,+BAAgC,CAChC,+BAAgC,CAChC,+BAAgC,CAChC,mCAAoC,CAGpC,uCAAwC,CACxC,sEAAuE,CAGvE,mDAAwD,CACxD,0CAA2C,CAC3C,2CAA4C,CAC5C,mDAAoD,CACpD,qDAAsD,CACtD,gDAAiD,CACjD,+CAAgD,CAChD,mDAAoD,CACpD,uCAAwC,CAGxC,8DAA+D,CAC/D,8BAA+B,CAC/B,sCAAuC,CACvC,sCAAuC,CACvC,qCAAsC,CACtC,mCAAoC,CACpC,uCAAwC,CACxC,uCAAwC,CACxC,kCAAmC,CACnC,4CAA6C,CAC7C,mCAAoC,CACpC,mCAAoC,CACpC,uCAAwC,CACxC,uCAAwC,CACxC,oCAAqC,CAGrC,mCAAoC,CACpC,gCAAiC,CAGjC,kCAAmC,CACnC,qCAAsC,CACtC,+DAAgE,CAChE,6CAAoD,CACpD,6CACF,CC9CA,KACE,qBACF,CAEA,iBAGE,kBACF,CAEA,KACE,6BAAsB,CAAtB,0BAAsB,CAAtB,qBACF,CCZA,KAEE,+BAAgC,CADhC,WAAY,CAGZ,eAAgB,CADhB,sBAEF,CAEA,KAOE,6CAA8C,CAD9C,4BAA6B,CAF7B,8BAA+B,CAC/B,8BAA+B,CAJ/B,QAAS,CACT,sBAAuB,CACvB,wBAKF,CAEA,EACE,oBACF,CAEA,QACE,yBACF,CAEA,SACE,qBACF,CAEA,aAGE,wCACF,CAEA,iCACE,OAEE,wDAAyD,CADzD,oBAEF,CACF,CAEA,MAEE,gBAAiB,CADjB,wBAEF,CAEA,KACE,uCACF,CCjDA,kBAGE,kDAAmD,CAFnD,kCAAmC,CACnC,eAEF,CAEA,QAEE,sIAC0E,CAC1E,4CAA+C,CAH/C,WAIF,CAEA,KACE,aACF,CAEA,WAEE,aAAc,CADd,iCAEF,CAEA,qCAEE,YACF,CAEA,yBACE,aAAc,CACd,WAAY,CACZ,kBACF,CAEA,oBACE,uBAAgB,CAAhB,oBAAgB,CAAhB,eAAgB,CAKhB,6IAEuE,CACvE,2DAA4D,CAL5D,WAAY,CAOZ,YAAa,CATb,iBAAkB,CAClB,UASF,CAEA,+CAJE,kBAAmB,CALnB,8CAoBF,CAXA,2BASE,uDAAwD,CAPxD,UAAW,CAIX,WAAY,CAFZ,QAAS,CADT,iBAAkB,CAElB,OAAQ,CAKR,wBAA2B,CAH3B,UAIF,CAEA,iCACE,6DACF,CAEA,mCACE,0BACF,CCxEA,KACE,mCAAoC,CACpC,oBAAa,CAAb,YAAa,CAEb,8BAAgC,CADhC,eAAgB,CAEhB,QACF,CAIA,2BAEE,aACF,CAEA,wBAEE,gBAAiB,CACjB,iBACF,CAEA,cACE,mBACF,CAIA,KACE,uCAA6C,CAC7C,+CACF,CAEA,aACE,8DACF,CAIA,sBACE,gDAAiD,CACjD,2CAA4C,CAG5C,cAAgB,CADhB,eAAgB,CADhB,mBAGF,CAEA,yBACE,YAAa,CACb,cACF,CAEA,oBACE,YACF,CAEA,2DAIE,+CAAgD,CAHhD,eAAgB,CAChB,eAAgB,CAChB,WAEF,CAEA,6CACE,YACF,CAEA,iCACE,eAAgB,CAGhB,eAAgB,CAFhB,gBAAkB,CAClB,yBAEF,CAIA,yCAEE,eACF,CAEA,mBACE,6DACF,CAIA,QACE,eACF,CAEA,QACE,aACF,CAEA,QACE,eACF,CAEA,QACE,eACF,CAEA,QACE,eACF,CAEA,QACE,eACF,CAEA,gDAME,2CAA4C,CAC5C,kDAAmD,CACnD,oBAAa,CAAb,YAAa,CACb,eAAgB,CAChB,iBAAkB,CAClB,kBACF,CAEA,cACE,iDAAkD,CAClD,eAAgB,CAChB,qBAAsB,CACtB,kBACF,CAEA,oBACE,eACF,CAEA,uBACE,iBAAkB,CAClB,kBAAmB,CACnB,yBACF,CAEA,uBACE,sDACF,CAIA,gGAYE,eAAmB,CAHnB,gBAAiB,CACjB,iBAAmB,CAJnB,iBAAkB,CAClB,oBAAqB,CAIrB,iBAAkB,CAHlB,YAKF,CAEA,0IAME,eACF,CAEA,oIAME,kBACF,CAEA,eAEE,QACF,CAIA,YACE,oBAAa,CAAb,YACF,CAEA,OACE,wCACF,CAEA,aACE,8CACF,CAEA,kBACE,mDACF,CAIA,uDAIE,6CAA8C,CAC9C,mBAAqB,CAFrB,wCAAyC,CAGzC,eAAiB,CACjB,oBACF,CAEA,6DAGE,6CACF,CAEA,mBAEE,oBAAa,CAAb,YACF,CAEA,SACE,sCAAyC,CACzC,eAAgB,CAChB,QACF,CAEA,sFAGE,4CAA6C,CAK7C,iBAAkB,CAJlB,+DAAgE,CAChE,aAAc,CACd,eAAgB,CAChB,cAEF,CAEA,0CASE,6CAA8C,CAR9C,uBAAwB,CAExB,aAAc,CAKd,eAAiB,CADjB,aAAc,CAHd,iBAAkB,CAElB,WAAa,CAJb,wBAAyB,CAGzB,SAKF,CAEA,mBACE,iBACF,CAEA,gDACE,YACF,CAIA,gBACE,QACF,CAEA,uBACE,sCACF,CAEA,qOAeE,eACF,CAIA,sBACE,aAAc,CAEd,eAAgB,CADhB,UAEF,CAEA,yBACE,cACF,CAEA,sBACE,sCAAyC,CACzC,iBACF,CAEA,wBACE,eACF,CAEA,yCACE,YACF,CAEA,kDAEE,aACF,CAEA,+BACE,+DACF,CAEA,8DAGE,6DAA8D,CAD9D,0DAEF,CAEA,0KAIE,qDACF,CAEA,4BACE,qDACF,CAEA,uEAGE,oBACF,CAEA,oHAGE,kBACF,CAIA,sBACE,eACF,CAEA,yDAEE,sCACF,CAEA,oGAEE,YACF,CAEA,0BAEE,WAAY,CADZ,sCAEF,CAEA,4BAEE,iBAAkB,CADlB,kBAAmB,CAEnB,UACF,CAEA,iCAIE,kBAAmB,CAFnB,mDAAoD,CADpD,wBAA0B,CAE1B,UAEF,CAEA,8BAOE,oBAAsB,CAHtB,sCAAyC,CADzC,MAAO,CAEP,aAAc,CAGd,oBAAuB,CAPvB,iBAAkB,CAClB,KAAM,CAIN,gCAGF,CAEA,8BAEE,kBAAmB,CAInB,0BAA4B,CAD5B,2BAA4B,CAJ5B,mBAAoB,CAMpB,mBAAoB,CAHpB,WAAY,CAIZ,gBAAiB,CACjB,sBAAuB,CANvB,UAOF,CAEA,oCACE,wCAA+C,CAK/C,8CAA+C,CAJ/C,mBAAoB,CAEpB,mBAAoB,CAGpB,iBAAkB,CAFlB,2DAA4D,CAG5D,oBAAa,CAAb,YAAa,CAEb,aAAe,CADf,cAAgB,CANhB,yBAQF,CAEA,KACE,yBACF,CAEA,kBACE,uDACF,CAEA,oBACE,sDACF,CAEA,eACE,sDACF,CAEA,cACE,4DACF,CAEA,kBACE,uDACF,CAEA,sCACE,2DACF,CAEA,wCACE,6DACF,CAEA,iCACE,wDACF,CAEA,gCACE,uDACF,CAEA,oCACE,iEACF,CAIA,iBAGE,kBAAmB,CAFnB,YAAa,CACb,qBAEF,CAEA,qCAEE,oBAAqB,CACrB,WAAY,CACZ,cAAe,CACf,qBACF,CAEA,uCACE,gBACF,CAIA,oCACE,iDAAkD,CAClD,8DAA+D,CAC/D,sCAAyC,CACzC,iBACF,CAEA,kCAEE,8CAA+C,CAC/C,2DACF,CAEA,iBACE,2BACF,CAEA,8BACE,qDAAsD,CACtD,sCAAyC,CACzC,iBACF,CAEA,4BACE,eACF,CAEA,4BACE,iBACF,CAEA,sBACE,gBACF,CAIA,iBACE,gBAAiB,CACjB,iBACF,CAEA,qBACE,mBAAoB,CACpB,iBACF,CAIA,gBAEE,QAAS,CACT,kBACF,CAEA,mHAOE,oBACF,CAEA,qCAEE,oBACF,CAEA,kCAEE,cACF,CAUA,2CACE,sBACF,CAEA,eACE,uBACF,CAEA,gBACE,oCACF,CAEA,mBACE,2BACF,CAEA,mBACE,2BACF,CAEA,mBACE,2BACF,CAEA,mBACE,2BACF,CAEA,mBACE,2BACF,CAEA,kBACE,kBACF,CAEA,kGAEE,mBAAoB,CACpB,sBAAuB,CACvB,aACF,CAEA,6CACE,eACF,CAEA,uCACE,eACF,CAEA,2KASE,gBACF,CAEA,8BAEE,mBACF,CAEA,wFAGE,SACF,CAIA,mLAOE,2CAA4C,CAC5C,sCAAyC,CAEzC,iBAAkB,CADlB,kDAAmD,CAEnD,oBAAa,CAAb,YAAa,CACb,oBAAsB,CACtB,sBAAwB,CACxB,eACF,CAEA,wBACE,gBAAkB,CAClB,gBACF,CAIA,4BACE,gDAAiD,CACjD,wDAAyD,CACzD,iBAAkB,CAClB,cACF,CAEA,yCACE,YACF,CAIA,mBACE,gDAAiD,CACjD,cACF,CAEA,mCACE,sCAAyC,CACzC,sDAAuD,CACvD,eAAgB,CAChB,oBACF,CAEA,qDACE,YACF,CAIA,cACE,kBACF,CAEA,qBACE,WAAY,CACZ,mBACF,CAEA,oBACE,WAAY,CACZ,kBACF,CAIA,yBAEE,oBAAa,CAAb,YACF,CAEA,6BACE,eAAgB,CAChB,eAAgB,CAChB,oDAAqD,CACrD,kBACF,CAIA,SAGE,4CAA6C,CAC7C,oDAAqD,CACrD,mBAAqB,CACrB,8FAC0C,CAN1C,oBAAqB,CACrB,sCAAyC,CAMzC,kBAAqB,CACrB,0BAA2B,CAC3B,kBACF,CAEA,sBAEE,aACF,CAEA,aACE,sCACF,CAEA,iBACE,eACF,CAEA,6BACE,aACF,CAEA,4BACE,cACF,CAIA,UAEE,iBAAkB,CADlB,oBAAa,CAAb,YAEF,CAEA,kCACE,wBAAiB,CAAjB,qBAAiB,CAAjB,gBACF,CAEA,eACE,iBACF,CAEA,eACE,wBACF,CAEA,4BACE,eACF,CAEA,gCAEE,iBAAmB,CACnB,kBACF,CAEA,0DAEE,aACF,CAEA,gBACE,wCAAyC,CACzC,oBACF,CAEA,gBACE,mBACF,CAEA,aACE,sCAAyC,CACzC,uBACF,CAEA,4EAEE,qBAAwB,CACxB,kBACF,CAEA,0EAEE,gBACF,CAEA,wBAaE,gDAAiD,CAVjD,kBAAmB,CAWnB,2CAA4C,CAV5C,oBAAqB,CAFrB,wCAAyC,CAGzC,wCAA2C,CAC3C,iBAAkB,CAIlB,aAAc,CACd,qBAAuB,CAJvB,eAAgB,CAChB,iBAAkB,CAIlB,kBAAoB,CAHpB,YAMF,CAEA,8BACE,wBACF,CAEA,0BACE,YACF,CAEA,QACE,qDAAsD,CACtD,oBAAqB,CACrB,QACF,CAIA,sBACE,kBACF,CAEA,cAEE,gBAAiB,CADjB,oBAAa,CAAb,YAEF,CAEA,YACE,WACF,CAEA,WACE,UACF,CAEA,cACE,UACF,CAEA,gBACE,yBACF,CAEA,mBACE,4BACF,CAEA,kBACE,eACF,CAEA,mBACE,gBACF,CAEA,oBACE,iBACF,CAEA,iBACE,kBACF,CAEA,oBACE,qBACF,CAEA,oBACE,qBACF,CAIA,qBAIE,6DAA8D,CAF9D,0CAA2C,CAD3C,sCAAyC,CAEzC,cAEF,CAIA,qBACE,uCAA6C,CAC7C,oDACF,CAEA,qCACE,KACE,sCAA4C,CAC5C,+CACF,CACA,qBACE,sCAA4C,CAC5C,oDACF,CACF,CAEA,oCACE,0BAEE,eACF,CACF,CC36BA,MAIE,4CAA6C,CAC7C,iCAAkC,CAJlC,aAAc,CACd,eAAgB,CAChB,YAGF,CAEA,6CAGE,yCACF,CAEA,0BAEE,yCACF,CAEA,0BAEE,wCACF,CAEA,WACE,sCACF,CAEA,0EAKE,0CACF,CAEA,uCAEE,0CACF,CAEA,qCAGE,qCACF,CAEA,qBACE,+CACF,CAEA,mCAEE,sCACF,CAEA,aACE,uCACF,CAEA,WAEE,sCAAuC,CADvC,yBAEF,CAEA,eACE,0CACF,CAEA,eACE,0CACF,CAEA,eACE,iBACF,CAEA,aACE,eACF,CAEA,yDAEE,0CACF,CAEA,0BACE,wCACF,CCtFA,QACE,YACF,CAEA,WAGE,iBAAkB,CAGlB,QAAS,CAFT,oBAAqB,CAFrB,sCAAyC,CADzC,eAAiB,CAOjB,yCAA4C,CAD5C,gBAAkB,CAFlB,iBAIF,CAMA,sCAHE,yCAaF,CAVA,UAEE,6CAA8C,CAM9C,eAAgB,CALhB,4BAA6B,CAE7B,cAAe,CADf,oBAAqB,CAGrB,yCAA4C,CAN5C,mBAAsB,CAQtB,+BACF,CAEA,gBAEE,6CAA8C,CAD9C,kCAAmC,CAEnC,yBACF,CAEA,mBACE,sDAAuD,CACvD,kDAAmD,CACnD,qCACF,CAEA,yBACE,qCAAsC,CACtC,oBACF,CAEA,yCAEE,mDAAoD,CADpD,YAEF,CCrDA,mBACE,gDAAiD,CAEjD,4BAA6B,CAD7B,aAEF,CAEA,KAME,iDAAkD,CALlD,0BAA2B,CAO3B,gBAAkB,CAClB,eAAgB,CAJhB,qCAAwC,CAExC,qBAA2B,CAL3B,iBAAkB,CAClB,+BAAgC,CAChC,sBAMF,CAEA,UACE,YACF,CAEA,gBAEE,SACF,CAEA,sBAEE,kBACF,CAEA,QACE,aAAc,CACd,eACF,CAEA,OAKE,iBAAkB,CAFlB,2BAA4B,CAF5B,aAAc,CAGd,mBAAsB,CAFtB,oBAIF,CAEA,aACE,kDACF,CAEA,oBAIE,WAAY,CADZ,iBAAkB,CAFlB,cAAe,CACf,KAGF,CAEA,iBACE,mDAAoD,CACpD,kCACF,CAEA,sBAEE,YACF,CAEA,sEAIE,aACF,CAEA,eACE,aAAc,CACd,mBACF,CAEA,iBAEE,mBAAqB,CACrB,iBAAmB,CAFnB,mBAGF,CAEA,wBAGE,kCAAwC,CACxC,8DAAiE,CAHjE,UAAW,CAIX,aAAc,CAHd,sCAAuC,CAOvC,WAAY,CADZ,eAAgB,CADhB,cAAe,CADf,iBAIF,CAEA,kBAOE,6CAA8C,CAC9C,iDAAkD,CAPlD,8BAA+B,CAK/B,2BAA4B,CAJ5B,UAAW,CAOX,aANF,CASA,QAEE,WAAY,CACZ,gBAAiB,CAFjB,UAGF,CAEA,iCACE,cAAe,CACf,KACF,CAEA,kBAIE,kCAAwC,CACxC,4DAA+D,CAC/D,WAAY,CAGZ,aAAc,CANd,mCAAoC,CADpC,4BAA6B,CAK7B,YAAa,CACb,SAAU,CAPV,2BASF,CAEA,gCACE,mDACF,CAEA,oCACE,oBACE,yBACF,CAEA,KAKE,6CAA8C,CAF9C,WAAY,CACZ,MAAO,CAHP,6DAA8D,CAC9D,UAAW,CAIX,aACF,CAEA,mBACE,aACF,CACF,CCxJA,cACE,mBAAoB,CACpB,oBAAqB,CACrB,gBAAiB,CAKjB,4CAA6C,CAG7C,8CAA+C,CAD/C,iBAAkB,CAJlB,UAAW,CAFX,YAAa,CAQb,SAAU,CAHV,SAAU,CAJV,iBAAkB,CAElB,SAAU,CAMV,mCACF,CAEA,uCACE,SACF,CAEA,qBAIE,kCAAwC,CACxC,WAAY,CAFZ,qCAAsC,CADtC,2BAA4B,CAK5B,YAAa,CADb,SAAU,CALV,yBAOF,CAEA,sCACE,qDACF,CAEA,2BACE,wDAAyD,CACzD,qBACF,CAEA,4BACE,4CAA6C,CAC7C,sBACF,CAEA,gCACE,YACF,CAEA,iCACE,wDACF,CAEA,mCACE,wDACF,CAEA,iCACE,sDACF,CAEA,0BAGE,UAAW,CADX,aAAc,CAId,2BAA4B,CAL5B,SAAU,CAGV,iBAAkB,CAIlB,sBAAyB,CAHzB,yBAA0B,CAE1B,eAEF,CAEA,wCACE,eAAgB,CAChB,sBACF,CAEA,iCAME,sEAAuE,CACvE,wFACa,CANb,iCAAoC,CAGpC,UAAW,CAFX,QAAS,CACT,sCAAyC,CAHzC,iBAQF,CAEA,gCAME,wDAAyD,CAGzD,iBAAkB,CAFlB,uCAAwC,CANxC,8BAA+B,CAS/B,eAAiB,CALjB,yCAA4C,CAG5C,eAAgB,CANhB,iBAAkB,CAElB,UAAW,CADX,kDAQF,CAEA,yCACE,SACF,CAEA,gBAGE,UAAW,CADX,UAAW,CAGX,eAAgB,CADhB,oBAAsB,CAHtB,iBAKF,CAEA,sGAEE,kBAAmB,CACnB,SACF,CAEA,sGAEE,YAAe,CACf,SACF,CAEA,gDACE,gBAAiB,CACjB,SACF,CAEA,gDACE,gBAAiB,CACjB,SACF,CAEA,gGAEE,YAAa,CACb,SACF,CAEA,kDACE,kEACF,CAMA,gGACE,kEACF,CAEA,8CACE,kEACF","file":"site.css","sourcesContent":["/*\n * Copyright 2021 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n:root {\n /* NOTE: Don't use relative `url()` values in here. Safari load them properly */\n\n /* General */\n --html-font-size: 1em;\n --pixel-to-rem: 16 * 1rem;\n --font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto,\n Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\",\n \"Segoe UI Symbol\";\n --font-weight: 400;\n --monospace-font-family: \"SFMono-Regular\", \"Consolas\", \"Liberation Mono\",\n \"Menlo\", monospace;\n --body-background-color: white;\n --panel-background-color: #f6f8fa;\n --panel-group-background-color: #e1e8e8;\n --panel-border-color: #eaedf0;\n --color-accent-1: #ebf2f2;\n --color-accent-2: #d7e7e7;\n --color-accent-3: #6db33f;\n --body-font-color: #191e1e;\n --body-font-light-color: #273030;\n --body-font-dark-color: #141818;\n --link-font-color: #1565c0;\n --hover-link-font-color: #104d92;\n --scrollbar-thumb-color: silver;\n --mark-background-color: #39ff14;\n --selected-background-color: #191e1e;\n\n /* Layout */\n --layout-banner-logo-offset: 18px;\n --layout-banner-logo-height: 50px;\n --layout-max-width: 1400px;\n --layout-banner-height: 80px;\n --layout-border-color: var(--color-accent-1);\n --layout-switchtheme-invert-filter: invert();\n --layout-switchtheme-background-color: var(--body-background-color);\n --layout-switchtheme-button-color: var(--body-background-color);\n --layout-switchtheme-button-hover-color: var(--color-accent-1);\n\n /* Asciidoctor */\n --asciidoctor-doc-embellishment-margin-width: 250px;\n --asciidoctor-doc-background-embellishment-height: 147px;\n --asciidoctor-details-background: var(--color-accent-1);\n --asciidoctor-details-font-color: var(--body-font-light-color);\n --asciidoctor-author-separator-color: var(--color-accent-3);\n --asciidoctor-panel-background: var(--panel-background-color);\n --asciidoctor-panel-border-color: var(--panel-border-color);\n --asciidoctor-font-color: var(--body-font-color);\n --asciidoctor-heading-font-color: var(--body-font-dark-color);\n --asciidoctor-heading-font-weight: 600;\n --asciidoctor-alt-heading-font-weight: 600;\n --asciidoctor-section-divider-color: var(--color-accent-1);\n --asciidoctor-link-font-color: var(--link-font-color);\n --asciidoctor-hover-link-font-color: var(--hover-link-font-color);\n --asciidoctor-unresolved-link-font-color: #d32f2f;\n --asciidoctor-code-font-color: var(--asciidoctor-font-color);\n --asciidoctor-code-link-font-color: var(--link-font-color);\n --asciidoctor-code-background: rgba(27, 31, 35, 0.05);\n --asciidoctor-code-data-lang-color: #999;\n --asciidoctor-table-border-color: var(--asciidoctor-panel-border-color);\n --asciidoctor-table-header-footer-background: var(--color-accent-1);\n --asciidoctor-table-stripe-background: var(--color-accent-1);\n --asciidoctor-table-footer-background: linear-gradient(\n to bottom,\n var(--color-accent-1) 0%,\n var(--body-background-color) 100%\n );\n --asciidoctor-admonition-background: var(--color-accent-1);\n --asciidoctor-admonition-pre-background: var(--color-accent-2);\n --asciidoctor-admonition-label-font-weight: 500;\n --asciidoctor-admonition-font-color: #f0f0f0;\n --asciidoctor-admonition-caution-background: #561164;\n --asciidoctor-admonition-important-background: #960000;\n --asciidoctor-admonition-note-background: #015785;\n --asciidoctor-admonition-tip-background: #3e6b1f;\n --asciidoctor-admonition-warning-background: #bd7400;\n --asciidoctor-abstract-background: var(--asciidoctor-panel-background);\n --asciidoctor-abstract-border-color: var(--asciidoctor-panel-border-color);\n --asciidoctor-quote-background: var(--color-accent-1);\n --asciidoctor-quote-border-color: var(--color-accent-3);\n --asciidoctor-quote-attribution-font-color: var(--color-accent-3);\n --asciidoctor-caption-font-color: var(--body-font-light-color);\n --asciidoctor-caption-font-weight: 400;\n --asciidoctor-example-background: var(--asciidoctor-panel-background);\n --asciidoctor-example-border-color: var(--asciidoctor-panel-border-color);\n --asciidoctor-sidebar-background: var(--color-accent-1);\n --asciidoctor-pre-background: var(--asciidoctor-panel-background);\n --asciidoctor-pre-border-color: var(--asciidoctor-panel-border-color);\n --asciidoctor-callout-background: var(--body-font-dark-color);\n --asciidoctor-callout-font-color: var(--body-background-color);\n --asciidoctor-footer-font-color: #b6b6b6;\n\n /* Highlight JS (colors based on https://github.com/primer/github-syntax-light) */\n --highlight-background-color: var(--asciidoctor-pre-background);\n --highlight-font-color: #24292e;\n --highlight-keyword-font-color: #d73a49;\n --highlight-comment-font-color: #6a737d;\n --highlight-string-font-color: #032f62;\n --highlight-meta-font-color: #6a737d;\n --highlight-constant-font-color: #032f62;\n --highlight-variable-font-color: #005cc5;\n --highlight-tag-font-color: #22863a;\n --highlight-tag-attribute-font-color: #6f42c1;\n --highlight-type-font-color: #6f42c1;\n --highlight-link-font-color: var(--link-font-color);\n --highlight-addition-font-color: #22863a;\n --highlight-deletion-font-color: #24292e;\n --highlight-regex-font-color: #032f62;\n\n /* Tabs */\n --tabs-border-color: var(--selected-background-color);\n --tabs-background-color: var(--body-background-color);\n --tabs-font-color: var(--body-font-color);\n --tabs-selected-background-color: var(--selected-background-color);\n --tabs-selected-font-color: var(--body-background-color);\n --tabs-hover-font-color: var(--hover-link-font-color);\n --tabs-hover-background: var(--color-accent-1);\n --tabs-group-background-color: var(--panel-group-background-color);\n\n /* TOC */\n --toc-width: 24rem;\n --toc-display: block;\n --toc-font-color: var(--body-font-color);\n --toc-hover-background-color: var(--color-accent-1);\n --toc-active-background-color: var(--selected-background-color);\n --toc-active-font-color: var(--body-background-color);\n --toc-back-to-index-filter: none;\n --toc-bar-display: none;\n --toc-bar-height: 0;\n --toc-bar-button-filter: none;\n\n /* Code Tools */\n --codetools-button-filter: none;\n --codetools-button-active-filter: invert();\n --codetools-background-color: var(--body-background-color);\n --codetools-border-color: rgba(0, 0, 0, 0.3);\n --codetools-hover-background-color: var(--color-accent-1);\n --codetools-divider-color: var(--codetools-border-color);\n --codetools-popup-background-color: var(--selected-background-color);\n --codetools-popup-font-color: var(--body-background-color);\n}\n\n/* Responsive Overrides */\n\n@media screen and (max-width: 1024px) {\n :root {\n --toc-width: 16rem;\n --asciidoctor-doc-embellishment-margin-width: 140px;\n }\n}\n\n@media screen and (max-width: 800px) {\n :root {\n --layout-banner-height: 51px;\n --layout-banner-logo-height: 30px;\n --layout-banner-logo-offset: 10px;\n --layout-border-color: var(--body-background-color);\n --toc-bar-display: block;\n --toc-bar-height: 24px;\n --toc-width: 0;\n --toc-display: none;\n --asciidoctor-doc-embellishment-margin-width: 0;\n }\n}\n","html.dark-theme {\n /* General */\n --font-weight: 300;\n --body-background-color: #1b1f23;\n --panel-background-color: #262a2d;\n --panel-group-background-color: #303741;\n --panel-border-color: #2c3135;\n --color-accent-1: #272c33;\n --color-accent-1-invert: #d8d3cc;\n --color-accent-2: #2d333a;\n --color-accent-3: #6db33f;\n --body-font-color: #bbbcbe;\n --body-font-light-color: #abacaf;\n --body-font-dark-color: #cecfd1;\n --link-font-color: #086dc3;\n --hover-link-font-color: #107ddd;\n --scrollbar-thumb-color: #5f5f5f;\n --mark-background-color: #2eca12;\n --selected-background-color: #8d8d8d;\n\n /* Layout */\n --layout-switchtheme-invert-filter: none;\n --layout-switchtheme-background-color: var(--selected-background-color);\n\n /* Asciidoctor */\n --asciidoctor-code-background: rgba(177, 209, 241, 0.15);\n --asciidoctor-code-data-lang-color: #6e6e6e;\n --asciidoctor-admonition-font-color: #f0f0f0;\n --asciidoctor-admonition-caution-background: #603668;\n --asciidoctor-admonition-important-background: #924040;\n --asciidoctor-admonition-note-background: #355463;\n --asciidoctor-admonition-tip-background: #4d6340;\n --asciidoctor-admonition-warning-background: #967745;\n --asciidoctor-footer-font-color: #5e5e5e;\n\n /* Highlight JS (colors based on https://github.com/primer/github-syntax-dark) */\n --highlight-background-color: var(--asciidoctor-pre-background);\n --highlight-font-color: #f6f8fa;\n --highlight-keyword-font-color: #ea4a5a;\n --highlight-comment-font-color: #959da5;\n --highlight-string-font-color: #79b8ff;\n --highlight-meta-font-color: #959da5;\n --highlight-constant-font-color: #79b8ff;\n --highlight-variable-font-color: #c8e1ff;\n --highlight-tag-font-color: #7bcc72;\n --highlight-tag-attribute-font-color: #b392f0;\n --highlight-type-font-color: #b392f0;\n --highlight-link-font-color: #1565c0;\n --highlight-addition-font-color: #7bcc72;\n --highlight-deletion-font-color: #f6f8fa;\n --highlight-regex-font-color: #79b8ff;\n\n /* TOC */\n --toc-back-to-index-filter: invert();\n --toc-bar-button-filter: invert();\n\n /* Code Tools */\n --codetools-button-filter: invert();\n --codetools-button-active-filter: none;\n --codetools-hover-background-color: var(--color-accent-1-invert);\n --codetools-border-color: rgba(255, 255, 255, 0.274);\n --codetools-divider-color: rgba(44, 44, 44, 0.274);\n}\n","/*\n * Copyright 2021 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nhtml {\n box-sizing: border-box;\n}\n\n*,\n*:before,\n*:after {\n box-sizing: inherit;\n}\n\nbody {\n text-size-adjust: none;\n}\n","/*\n * Copyright 2021 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nhtml {\n height: 100%;\n font-size: var(--html-font-size);\n scroll-behavior: smooth;\n min-width: 340px;\n}\n\nbody {\n margin: 0;\n overflow-wrap: anywhere;\n overscroll-behavior: none;\n font-family: var(--font-family);\n font-weight: var(--font-weight);\n color: var(--body-font-color);\n background-color: var(--body-background-color);\n}\n\na {\n text-decoration: none;\n}\n\na:hover {\n text-decoration: underline;\n}\n\na:active {\n background-color: none;\n}\n\ncode,\nkbd,\npre {\n font-family: var(--monospace-font-family);\n}\n\n@supports (scrollbar-width: thin) {\n body * {\n scrollbar-width: thin;\n scrollbar-color: var(--scrollbar-thumb-color) transparent;\n }\n}\n\ntable {\n border-collapse: collapse;\n word-wrap: normal;\n}\n\nmark {\n background: var(--mark-background-color);\n}\n","/*\n * Copyright 2021 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#banner-container {\n height: var(--layout-banner-height);\n overflow: hidden;\n border-bottom: 1px solid var(--layout-border-color);\n}\n\n#banner {\n height: 100%;\n background: no-repeat top var(--layout-banner-logo-offset) left\n var(--layout-banner-logo-offset) / auto var(--layout-banner-logo-height);\n background-image: url(\"../img/banner-logo.svg\");\n}\n\n#doc {\n overflow: auto;\n}\n\n.contained {\n max-width: var(--layout-max-width);\n margin: 0 auto;\n}\n\ndiv#switch-theme,\n#switch-theme label {\n display: none;\n}\n\nhtml.js div#switch-theme {\n display: block;\n float: right;\n margin: 8px 6px 0 0;\n}\n\n#switch-theme input {\n appearance: none;\n position: relative;\n width: 40px;\n height: 22px;\n filter: var(--layout-switchtheme-invert-filter);\n background: no-repeat url(\"../img/octicons-16.svg#view-sun\") 90% 50% / 16px\n 16px,\n no-repeat url(\"../img/octicons-16.svg#view-moon\") 10% 50% / 16px 16px;\n background-color: var(--layout-switchtheme-background-color);\n border-radius: 25px;\n outline: none;\n}\n\n#switch-theme input::before {\n filter: var(--layout-switchtheme-invert-filter);\n content: \"\";\n position: absolute;\n left: 2px;\n top: 2px;\n height: 18px;\n width: 18px;\n border-radius: 25px;\n background-color: var(--layout-switchtheme-button-color);\n transition: transform 200ms;\n}\n\n#switch-theme:hover input::before {\n background-color: var(--layout-switchtheme-button-hover-color);\n}\n\n#switch-theme input:checked::before {\n transform: translateX(18px);\n}\n","/*\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n */\n\n/* Asciidoctor styling based on https://gitlab.com/antora/antora-ui-default/-/blob/8751b86b76d6779fbbcf0fccd58fafcf73c49260/src/css/doc.css */\n\n/* Container element styling */\n\n.doc {\n color: var(--asciidoctor-font-color);\n hyphens: none;\n line-height: 1.6;\n letter-spacing: -0.0027777778rem;\n margin: 0;\n}\n\n/* Gutter and margins */\n\n.doc #content,\n.doc #footer {\n margin: 0 2rem;\n}\n\n.doc #header > *:not(#toc) {\n /* Gutter is not applied directly to #header of toc positioning */\n margin-left: 2rem;\n margin-right: 2rem;\n}\n\n.doc #content {\n padding-bottom: 4rem;\n}\n\n/* Doc background embellishment */\n\n#doc {\n background: no-repeat top right / 305px 147px;\n background-image: url(\"../img/doc-background.svg\");\n}\n\n.doc #header {\n margin-right: var(--asciidoctor-doc-embellishment-margin-width);\n}\n\n/* Header Details */\n\n.doc #header .details {\n background: var(--asciidoctor-details-background);\n color: var(--asciidoctor-details-font-color);\n padding: 1rem 1.5rem;\n font-weight: 600;\n font-size: 0.8em;\n}\n\n.doc #header div.details {\n display: flex;\n flex-wrap: wrap;\n}\n\n#header .details br {\n display: none;\n}\n\n.doc #header .details span.author:not(:last-of-type)::after {\n content: \"\\2022\";\n font-weight: 400;\n margin: 0.4em;\n color: var(--asciidoctor-author-separator-color);\n}\n\n.doc #header .details span.last-author::after {\n display: none;\n}\n\n.doc #header .details #revnumber {\n flex-basis: 100%;\n margin-top: 0.5rem;\n text-transform: capitalize;\n font-weight: 200;\n}\n\n/* Section setup */\n\n.doc #preamble + .sect1,\n.doc .sect1 + .sect1 {\n margin-top: 2rem;\n}\n\n.doc .sect1 + .sect1 {\n border-top: 1px solid var(--asciidoctor-section-divider-color);\n}\n\n/* Headings */\n\n.doc h1 {\n font-size: 2.3em;\n}\n\n.doc h2 {\n font-size: 2em;\n}\n\n.doc h3 {\n font-size: 1.7em;\n}\n\n.doc h4 {\n font-size: 1.6em;\n}\n\n.doc h5 {\n font-size: 1.4em;\n}\n\n.doc h6 {\n font-size: 1.3em;\n}\n\n.doc h1,\n.doc h2,\n.doc h3,\n.doc h4,\n.doc h5,\n.doc h6 {\n color: var(--asciidoctor-heading-font-color);\n font-weight: var(--asciidoctor-heading-font-weight);\n hyphens: none;\n line-height: 1.3;\n margin: 1.3rem 0 0;\n padding-top: 1.8rem;\n}\n\n.doc h1.sect0 {\n background: var(--asciidoctor-abstract-background);\n font-size: 1.8em;\n margin: 1.5rem -1rem 0;\n padding: 0.5rem 1rem;\n}\n\n.doc h1:first-child {\n margin: 1.3rem 0;\n}\n\n.doc h2:not(.discrete) {\n margin-left: -1rem;\n margin-right: -1rem;\n padding: 1.8rem 1rem 0.1rem;\n}\n\n.doc h3:not(.discrete) {\n font-weight: var(--asciidoctor-alt-heading-font-weight);\n}\n\n/* Header hover anchors */\n\n.doc h1 .anchor,\n.doc h2 .anchor,\n.doc h3 .anchor,\n.doc h4 .anchor,\n.doc h5 .anchor,\n.doc h6 .anchor {\n position: absolute;\n text-decoration: none;\n width: 2.25ex;\n margin-left: -2ex;\n padding-left: 0.5ex;\n visibility: hidden;\n font-weight: normal;\n}\n\n.doc h1 .anchor::before,\n.doc h2 .anchor::before,\n.doc h3 .anchor::before,\n.doc h4 .anchor::before,\n.doc h5 .anchor::before,\n.doc h6 .anchor::before {\n content: \"\\0023\";\n}\n\n.doc h1:hover .anchor,\n.doc h2:hover .anchor,\n.doc h3:hover .anchor,\n.doc h4:hover .anchor,\n.doc h5:hover .anchor,\n.doc h6:hover .anchor {\n visibility: visible;\n}\n\n.doc p,\n.doc dl {\n margin: 0;\n}\n\n/* General anchors */\n\n.doc a.bare {\n hyphens: none;\n}\n\n.doc a {\n color: var(--asciidoctor-link-font-color);\n}\n\n.doc a:hover {\n color: var(--asciidoctor-hover-link-font-color);\n}\n\n.doc a.unresolved {\n color: var(--asciidoctor-unresolved-link-font-color);\n}\n\n/* Code and Pre */\n\n.doc p code,\n.doc thead code,\n.doc .admonitionblock code {\n color: var(--asciidoctor-code-font-color);\n background: var(--asciidoctor-code-background);\n border-radius: 0.25em;\n font-size: 0.95em;\n padding: 0.125em 0.25em;\n}\n\n.doc p a code,\n.doc thead a code,\n.doc .admonitionblock a code {\n color: var(--asciidoctor-code-link-font-color);\n}\n\n.doc code,\n.doc pre {\n hyphens: none;\n}\n\n.doc pre {\n font-size: calc(14 / var(--pixel-to-rem));\n line-height: 1.3;\n margin: 0;\n}\n\n.doc pre.highlight code,\n.doc .listingblock pre:not(.highlight),\n.doc .literalblock pre {\n background: var(--asciidoctor-pre-background);\n box-shadow: inset 0 0 1.75px var(--asciidoctor-pre-border-color);\n display: block;\n overflow-x: auto;\n padding: 0.95rem;\n border-radius: 4px;\n}\n\n.doc pre.highlight code[data-lang]:before {\n content: attr(data-lang);\n text-transform: uppercase;\n display: block;\n position: absolute;\n top: 0.3rem;\n right: 0.3rem;\n line-height: 1;\n font-size: 0.65em;\n color: var(--asciidoctor-code-data-lang-color);\n}\n\n.doc pre.highlight {\n position: relative;\n}\n\n.doc table pre.highlight code[data-lang]:before {\n display: none;\n}\n\n/* General margin and fonts sizing */\n\n.doc blockquote {\n margin: 0;\n}\n\n.doc .paragraph.lead > p {\n font-size: calc(18 / var(--pixel-to-rem));\n}\n\n.doc .paragraph,\n.doc .dlist,\n.doc .hdlist,\n.doc .olist,\n.doc .ulist,\n.doc .exampleblock,\n.doc .imageblock,\n.doc .listingblock,\n.doc .literalblock,\n.doc .sidebarblock,\n.doc .verseblock,\n.doc .quoteblock,\n.doc .partintro,\n.doc details,\n.doc hr {\n margin: 1rem 0 0;\n}\n\n/* Tables */\n\n.doc table.tableblock {\n display: block;\n width: 100%;\n overflow-x: auto;\n}\n\n.doc table.tableblock td {\n min-width: 6rem;\n}\n\n.doc table.tableblock {\n font-size: calc(15 / var(--pixel-to-rem));\n margin: 1.5rem 0 0;\n}\n\n.doc table.tableblock + * {\n margin-top: 2rem;\n}\n\n.doc td.tableblock > .content > :first-child {\n margin-top: 0;\n}\n\n.doc table.tableblock th,\n.doc table.tableblock td {\n padding: 0.5rem;\n}\n\n.doc table.tableblock thead th {\n border-bottom: 2.5px solid var(--asciidoctor-table-border-color);\n}\n\n.doc table.tableblock td,\n.doc table.tableblock > :not(thead) th {\n border-top: 1px solid var(--asciidoctor-table-border-color);\n border-bottom: 1px solid var(--asciidoctor-table-border-color);\n}\n\n.doc table.stripes-all > tbody > tr,\n.doc table.stripes-odd > tbody > tr:nth-of-type(odd),\n.doc table.stripes-even > tbody > tr:nth-of-type(even),\n.doc table.stripes-hover > tbody > tr:hover {\n background: var(--asciidoctor-table-stripe-background);\n}\n\n.doc table.tableblock > tfoot {\n background: var(--asciidoctor-table-footer-background);\n}\n\n.doc .tableblock pre,\n.doc .tableblock code,\n.doc .listingblock.wrap pre {\n white-space: pre-wrap;\n}\n\n.doc td:nth-child(1) .tableblock pre,\n.doc td:nth-child(1) .tableblock code,\n.doc td:nth-child(1) .listingblock.wrap pre {\n white-space: nowrap;\n}\n\n/* Admonition blocks */\n\n.doc .admonitionblock {\n margin: 2.5rem 0;\n}\n\n.doc .admonitionblock p,\n.doc .admonitionblock td.content {\n font-size: calc(16 / var(--pixel-to-rem));\n}\n\n.doc .admonitionblock td.content > :not(.title):first-child,\n.doc .admonitionblock td.content > .title + * {\n margin-top: 0;\n}\n\n.doc .admonitionblock pre {\n font-size: calc(14 / var(--pixel-to-rem));\n border: none;\n}\n\n.doc .admonitionblock > table {\n table-layout: fixed;\n position: relative;\n width: 100%;\n}\n\n.doc .admonitionblock td.content {\n padding: 1rem 1rem 0.75rem;\n background: var(--asciidoctor-admonition-background);\n width: 100%;\n word-wrap: anywhere;\n}\n\n.doc .admonitionblock td.icon {\n position: absolute;\n top: 0;\n left: 0;\n font-size: calc(16 / var(--pixel-to-rem));\n line-height: 1;\n transform: translate(-0.5rem, -50%);\n border-radius: 0.45rem;\n padding: 0.25em 0.075em;\n}\n\n.doc .admonitionblock .icon i {\n display: inline-flex;\n align-items: center;\n width: auto;\n height: 16px;\n background-repeat: no-repeat;\n background-position: 0.5em 0;\n filter: invert(100%);\n padding-left: 2em;\n vertical-align: initial;\n}\n\n.doc .admonitionblock .icon i::after {\n border-left: 1px solid rgba(255, 255, 255, 0.3);\n content: attr(title);\n text-transform: capitalize;\n filter: invert(100%);\n font-weight: var(--asciidoctor-admonition-label-font-weight);\n color: var(--asciidoctor-admonition-font-color);\n font-style: normal;\n hyphens: none;\n padding: 0 0.5em;\n margin: -0.05em;\n}\n\ni.fa {\n background-size: 16px 16px;\n}\n\ni.fa.icon-caution {\n background-image: url(\"../img/octicons-16.svg#view-flame\");\n}\n\ni.fa.icon-important {\n background-image: url(\"../img/octicons-16.svg#view-stop\");\n}\n\ni.fa.icon-note {\n background-image: url(\"../img/octicons-16.svg#view-info\");\n}\n\ni.fa.icon-tip {\n background-image: url(\"../img/octicons-16.svg#view-light-bulb\");\n}\n\ni.fa.icon-warning {\n background-image: url(\"../img/octicons-16.svg#view-alert\");\n}\n\n.doc .admonitionblock.caution td.icon {\n background: var(--asciidoctor-admonition-caution-background);\n}\n\n.doc .admonitionblock.important td.icon {\n background: var(--asciidoctor-admonition-important-background);\n}\n\n.doc .admonitionblock.note .icon {\n background: var(--asciidoctor-admonition-note-background);\n}\n\n.doc .admonitionblock.tip .icon {\n background: var(--asciidoctor-admonition-tip-background);\n}\n\n.doc .admonitionblock.warning .icon {\n background-color: var(--asciidoctor-admonition-warning-background);\n}\n\n/* Images and image blocks */\n\n.doc .imageblock {\n display: flex;\n flex-direction: column;\n align-items: center;\n}\n\n.doc .imageblock img,\n.doc .image > img {\n display: inline-block;\n height: auto;\n max-width: 100%;\n vertical-align: middle;\n}\n\n.doc .image:not(.left):not(.right) > img {\n margin-top: -0.2em;\n}\n\n/* Quote blocks */\n\n.doc #preamble .abstract blockquote {\n background: var(--asciidoctor-abstract-background);\n border-left: 5px solid var(--asciidoctor-abstract-border-color);\n font-size: calc(16 / var(--pixel-to-rem));\n padding: 0.75em 1em;\n}\n\n.doc .quoteblock,\n.doc .verseblock {\n background: var(--asciidoctor-quote-background);\n border-left: 5px solid var(--asciidoctor-quote-border-color);\n}\n\n.doc .quoteblock {\n padding: 0.25rem 2rem 1.25rem;\n}\n\n.doc .quoteblock .attribution {\n color: var(--asciidoctor-quote-attribution-font-color);\n font-size: calc(15 / var(--pixel-to-rem));\n margin-top: 0.75rem;\n}\n\n.doc .quoteblock blockquote {\n margin-top: 1rem;\n}\n\n.doc .quoteblock .paragraph {\n font-style: italic;\n}\n\n.doc .quoteblock cite {\n padding-left: 1em;\n}\n\n/* Verse blocks */\n\n.doc .verseblock {\n font-size: 1.15em;\n padding: 1rem 2rem;\n}\n\n.doc .verseblock pre {\n font-family: inherit;\n font-size: inherit;\n}\n\n/* Lists */\n\n.doc ol,\n.doc ul {\n margin: 0;\n padding: 0 0 0 2rem;\n}\n\n.doc ul.checklist,\n.doc ul.none,\n.doc ol.none,\n.doc ul.no-bullet,\n.doc ol.unnumbered,\n.doc ul.unstyled,\n.doc ol.unstyled {\n list-style-type: none;\n}\n\n.doc ul.no-bullet,\n.doc ol.unnumbered {\n padding-left: 1.25rem;\n}\n\n.doc ul.unstyled,\n.doc ol.unstyled {\n padding-left: 0;\n}\n\n.doc ul.circle {\n list-style-type: square;\n}\n\n.doc ul.disc {\n list-style-type: square;\n}\n\n.doc ul.square {\n list-style-type: square;\n}\n\n.doc ol.arabic {\n list-style-type: decimal;\n}\n\n.doc ol.decimal {\n list-style-type: decimal-leading-zero;\n}\n\n.doc ol.loweralpha {\n list-style-type: lower-alpha;\n}\n\n.doc ol.upperalpha {\n list-style-type: upper-alpha;\n}\n\n.doc ol.lowerroman {\n list-style-type: lower-roman;\n}\n\n.doc ol.upperroman {\n list-style-type: upper-roman;\n}\n\n.doc ol.lowergreek {\n list-style-type: lower-greek;\n}\n\n.doc ul.checklist {\n padding-left: 0.5rem;\n}\n\n.doc ul.checklist p > i.fa-check-square-o:first-child,\n.doc ul.checklist p > i.fa-square-o:first-child {\n display: inline-flex;\n justify-content: center;\n width: 1.25rem;\n}\n\n.doc ul.checklist i.fa-check-square-o::before {\n content: \"\\2713\";\n}\n\n.doc ul.checklist i.fa-square-o::before {\n content: \"\\274f\";\n}\n\n.doc .dlist .dlist,\n.doc .dlist .olist,\n.doc .dlist .ulist,\n.doc .olist .dlist,\n.doc .olist .olist,\n.doc .olist .ulist,\n.doc .ulist .dlist,\n.doc .ulist .olist,\n.doc .ulist .ulist {\n margin-top: 0.5rem;\n}\n\n.doc .olist li,\n.doc .ulist li {\n margin-bottom: 0.3rem;\n}\n\n.doc .ulist .listingblock,\n.doc .olist .listingblock,\n.doc .admonitionblock .listingblock {\n padding: 0;\n}\n\n/* Block Titles */\n\n.doc .admonitionblock .title,\n.doc .exampleblock .title,\n.doc .imageblock .title,\n.doc .literalblock .title,\n.doc .listingblock .title,\n.doc .openblock .title,\n.doc .tableblock caption {\n color: var(--asciidoctor-caption-font-color);\n font-size: calc(14 / var(--pixel-to-rem));\n font-weight: var(--asciidoctor-caption-font-weight);\n font-style: italic;\n hyphens: none;\n letter-spacing: 0.01em;\n padding-bottom: 0.075rem;\n text-align: left;\n}\n\n.doc .imageblock .title {\n margin-top: 0.5rem;\n padding-bottom: 0;\n}\n\n/* Block content */\n\n.doc .exampleblock > .content {\n background: var(--asciidoctor-example-background);\n border: 1px solid var(--asciidoctor-example-border-color);\n border-radius: 4px;\n padding: 0.75rem;\n}\n\n.doc .exampleblock > .content > :first-child {\n margin-top: 0;\n}\n\n/* Sidebars */\n\n.doc .sidebarblock {\n background: var(--asciidoctor-sidebar-background);\n padding: 2.2rem 2.2rem;\n}\n\n.doc .sidebarblock > .content > .title {\n font-size: calc(23 / var(--pixel-to-rem));\n font-weight: var(--asciidoctor-alt-heading-font-weight);\n line-height: 1.3;\n margin-bottom: 1.2rem;\n}\n\n.doc .sidebarblock > .content > :not(.title):first-child {\n margin-top: 0;\n}\n\n/* Buttons (https://docs.asciidoctor.org/asciidoc/latest/macros/ui-macros/#button-macro-syntax) */\n\n.doc b.button {\n white-space: nowrap;\n}\n\n.doc b.button::before {\n content: \"[\";\n padding-right: 0.25em;\n}\n\n.doc b.button::after {\n content: \"]\";\n padding-left: 0.25em;\n}\n\n/* Menu (https://docs.asciidoctor.org/asciidoc/latest/macros/ui-macros/#menu-macro-syntax) */\n\n.doc .menuseq,\n.doc .path {\n hyphens: none;\n}\n\n.doc .menuseq i.caret::before {\n content: \"\\203a\";\n font-size: 1.1em;\n font-weight: var(--asciidoctor-body-font-weight-bold);\n line-height: calc(1 / 1.1);\n}\n\n/* Keyboard (https://docs.asciidoctor.org/asciidoc/latest/macros/keyboard-macro/) */\n\n.doc kbd {\n display: inline-block;\n font-size: calc(12 / var(--pixel-to-rem));\n background: var(--asciidoctor-kbd-background);\n border: 1px solid var(--asciidoctor-kbd-border-color);\n border-radius: 0.25em;\n box-shadow: 0 1px 0 var(--asciidoctor-kbd-border-color),\n 0 0 0 0.1em var(--body-background) inset;\n padding: 0.25em 0.5em;\n vertical-align: text-bottom;\n white-space: nowrap;\n}\n\n.doc kbd,\n.doc .keyseq {\n line-height: 1;\n}\n\n.doc .keyseq {\n font-size: calc(16 / var(--pixel-to-rem));\n}\n\n.doc .keyseq kbd {\n margin: 0 0.125em;\n}\n\n.doc .keyseq kbd:first-child {\n margin-left: 0;\n}\n\n.doc .keyseq kbd:last-child {\n margin-right: 0;\n}\n\n/* Misc */\n\n.doc i.fa {\n hyphens: none;\n font-style: normal;\n}\n\n.doc .language-console .hljs-meta {\n user-select: none;\n}\n\n.doc .dlist dt {\n font-style: italic;\n}\n\n.doc .dlist dd {\n margin: 0 0 0.25rem 1.5rem;\n}\n\n.doc .dlist dd:last-of-type {\n margin-bottom: 0;\n}\n\n.doc td.hdlist1,\n.doc td.hdlist2 {\n padding: 0.5rem 0 0;\n vertical-align: top;\n}\n\n.doc tr:first-child > .hdlist1,\n.doc tr:first-child > .hdlist2 {\n padding-top: 0;\n}\n\n.doc td.hdlist1 {\n font-weight: var(--body-font-weight-bold);\n padding-right: 0.25rem;\n}\n\n.doc td.hdlist2 {\n padding-left: 0.25rem;\n}\n\n.doc .colist {\n font-size: calc(16 / var(--pixel-to-rem));\n margin: 0.25rem 0 -0.25rem;\n}\n\n.doc .colist > table > tr > :first-child,\n.doc .colist > table > tbody > tr > :first-child {\n padding: 0.25em 0.5rem 0;\n vertical-align: top;\n}\n\n.doc .colist > table > tr > :last-child,\n.doc .colist > table > tbody > tr > :last-child {\n padding: 0.25rem 0;\n}\n\n.doc .conum[data-value] {\n /* border: 1px solid currentColor; */\n font-family: var(--monospace-font-family);\n border-radius: 100%;\n display: inline-block;\n font-size: calc(12.5 / var(--pixel-to-rem));\n font-style: normal;\n line-height: 1.2;\n text-align: center;\n width: 1.25em;\n height: 1.25em;\n letter-spacing: -0.25ex;\n text-indent: -0.25ex;\n background: var(--asciidoctor-callout-background);\n color: var(--asciidoctor-callout-font-color);\n}\n\n.doc .conum[data-value]::after {\n content: attr(data-value);\n}\n\n.doc .conum[data-value] + b {\n display: none;\n}\n\n.doc hr {\n border: solid var(--asciidoctor-section-divider-color);\n border-width: 2px 0 0;\n height: 0;\n}\n\n/* Pass-though Classes */\n\n.doc :not(pre).nowrap {\n white-space: nowrap;\n}\n\n.doc .nobreak {\n hyphens: none;\n word-wrap: normal;\n}\n\n.doc .right {\n float: right;\n}\n\n.doc .left {\n float: left;\n}\n\n.doc .stretch {\n width: 100%;\n}\n\n.doc .underline {\n text-decoration: underline;\n}\n\n.doc .line-through {\n text-decoration: line-through;\n}\n\n.doc .halign-left {\n text-align: left;\n}\n\n.doc .halign-right {\n text-align: right;\n}\n\n.doc .halign-center {\n text-align: center;\n}\n\n.doc .valign-top {\n vertical-align: top;\n}\n\n.doc .valign-bottom {\n vertical-align: bottom;\n}\n\n.doc .valign-middle {\n vertical-align: middle;\n}\n\n/* Footer */\n\n#footer #footer-text {\n font-size: calc(14 / var(--pixel-to-rem));\n color: var(--asciidoctor-footer-font-color);\n padding: 2rem 0;\n border-top: 1px solid var(--asciidoctor-section-divider-color);\n}\n\n/* Responsive and Dark Theme Overrides */\n\nhtml.dark-theme #doc {\n background: no-repeat top right / 305px 147px;\n background-image: url(\"../img/doc-background-dark.svg\");\n}\n\n@media screen and (max-width: 1024px) {\n #doc {\n background: no-repeat top right / 203px 95px;\n background-image: url(\"../img/doc-background.svg\");\n }\n html.dark-theme #doc {\n background: no-repeat top right / 203px 95px;\n background-image: url(\"../img/doc-background-dark.svg\");\n }\n}\n\n@media screen and (max-width: 800px) {\n html.dark-theme #doc,\n #doc {\n background: none;\n }\n}\n","/*\n * Copyright 2021 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n.hljs {\n display: block;\n overflow-x: auto;\n padding: 0.5em;\n background: var(--highlight-background-color);\n color: var(--highlight-font-color);\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-subst {\n color: var(--highlight-keyword-font-color);\n}\n\n.hljs-comment,\n.hljs-quote {\n color: var(--highlight-comment-font-color);\n}\n\n.hljs-string,\n.hljs-doctag {\n color: var(--highlight-string-font-color);\n}\n\n.hljs-meta {\n color: var(--highlight-meta-font-color);\n}\n\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-number,\n.hljs-symbol,\n.hljs-literal {\n color: var(--highlight-constant-font-color);\n}\n\n.hljs-variable,\n.hljs-template-variable {\n color: var(--highlight-variable-font-color);\n}\n\n.hljs-tag,\n.hljs-name,\n.hljs-attribute {\n color: var(--highlight-tag-font-color);\n}\n\n.hljs-tag .hljs-attr {\n color: var(--highlight-tag-attribute-font-color);\n}\n\n.hljs-type,\n.hljs-class .hljs-title {\n color: var(--highlight-type-font-color);\n}\n\n.hljs-regexp {\n color: var(--highlight-regex-font-color);\n}\n\n.hljs-link {\n text-decoration: underline;\n color: var(--highlight-link-font-color);\n}\n\n.hljs-addition {\n color: var(--highlight-addition-font-color);\n}\n\n.hljs-deletion {\n color: var(--highlight-deletion-font-color);\n}\n\n.hljs-emphasis {\n font-style: italic;\n}\n\n.hljs-strong {\n font-weight: bold;\n}\n\n.language-json .hljs-number,\n.language-json .hljs-literal {\n color: var(--highlight-variable-font-color);\n}\n\n.language-json .hljs-attr {\n color: var(--highlight-string-font-color);\n}\n","/*\n * Copyright 2021 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* Block Switching */\n\n.hidden {\n display: none;\n}\n\n.doc .tabs {\n font-weight: bold;\n font-size: calc(12 / var(--pixel-to-rem));\n border-style: none;\n display: inline-block;\n position: relative;\n bottom: 0;\n margin-top: 0.5rem;\n margin-bottom: calc(2 / var(--pixel-to-rem));\n}\n\n.doc .tab:not(:first-child) {\n border: 1px solid var(--tabs-border-color);\n}\n\n.doc .tab {\n padding: 0.3rem 0.6rem;\n background-color: var(--tabs-background-color);\n color: var(--tabs-font-color);\n display: inline-block;\n cursor: pointer;\n border: 1px solid var(--tabs-border-color);\n margin-bottom: calc(2 / var(--pixel-to-rem));\n border-radius: 0;\n transition: background-color 200ms;\n}\n\n.doc .tab:hover {\n color: var(--tabs-hover-font-color);\n background-color: var(--tabs-hover-background);\n text-decoration: underline;\n}\n\n.doc .tab.selected {\n background-color: var(--tabs-selected-background-color);\n border-color: var(--tabs-selected-background-color);\n color: var(--tabs-selected-font-color);\n}\n\n.doc .tab.selected:hover {\n color: var(--tabs-selected-font-color);\n text-decoration: none;\n}\n\n.doc div.openblock.tabs-content > .content {\n padding: 1rem;\n background-color: var(--tabs-group-background-color);\n}\n","/*\n * Copyright 2021 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nbody.toc-left #doc {\n border-left: 1px solid var(--layout-border-color);\n overflow: auto;\n margin-left: var(--toc-width);\n}\n\n#toc {\n display: var(--toc-display);\n position: absolute;\n top: var(--layout-banner-height);\n width: var(--toc-width);\n margin-left: calc(var(--toc-width) * -1);\n border-right: 1px solid var(--layout-border-color);\n padding: 1.7rem 1rem 0 1rem;\n font-size: 0.95rem;\n line-height: 1.1;\n}\n\n#toctitle {\n display: none;\n}\n\n#toc ul,\n#toc ol {\n padding: 0;\n}\n\n#toc ul ul,\n#toc ul ol {\n padding-left: 0.8rem;\n}\n\n#toc li {\n display: block;\n list-style: none;\n}\n\n#toc a {\n display: block;\n text-decoration: none;\n color: var(--toc-font-color);\n padding: 0.4rem 0.6rem;\n border-radius: 4px;\n}\n\n#toc a:hover {\n background-color: var(--toc-hover-background-color);\n}\n\nbody.fixed-toc #toc {\n position: fixed;\n top: 0;\n overflow-x: hidden;\n height: 100%;\n}\n\n#toc li.active > a {\n background-color: var(--toc-active-background-color);\n color: var(--toc-active-font-color);\n}\n\n#toc > ul ul,\n#toc > ol ol {\n display: none;\n}\n\n#toc li.active > ul,\n#toc li.active > ol,\n#toc ul.expanded,\n#toc ol.expanded {\n display: block;\n}\n\n#back-to-index {\n display: block;\n margin-bottom: 0.6rem;\n}\n\n#back-to-index a {\n padding-left: 1.6rem;\n margin-bottom: 0.6rem;\n margin-top: -0.9rem;\n}\n\n#back-to-index a::before {\n content: \"\";\n filter: var(--toc-back-to-index-filter);\n background: no-repeat center / 16px 16px;\n background-image: url(\"../img/octicons-16.svg#view-chevron-left\");\n display: block;\n position: absolute;\n min-width: 16px;\n min-height: 16px;\n left: 1.4rem;\n}\n\n#tocbar-container {\n display: var(--toc-bar-display);\n width: 100%;\n}\n\n#tocbar-container {\n height: var(--tocbar-height);\n background-color: var(--body-background-color);\n border-bottom: 1px solid var(--panel-border-color);\n z-index: 10000;\n}\n\n#tocbar {\n width: 100%;\n height: 100%;\n padding-left: 6px;\n}\n\nbody.fixed-toc #tocbar-container {\n position: fixed;\n top: 0;\n}\n\nbutton#toggle-toc {\n width: var(--toc-bar-height);\n height: var(--toc-bar-height);\n filter: var(--toc-bar-button-filter);\n background: no-repeat center / 16px 16px;\n background-image: url(\"../img/octicons-16.svg#view-three-bars\");\n border: none;\n outline: none;\n padding: 0;\n display: block;\n}\n\nbody.show-toc button#toggle-toc {\n background-image: url(\"../img/octicons-16.svg#view-x\");\n}\n\n@media screen and (max-width: 800px) {\n body.fixed-toc #toc {\n top: var(--toc-bar-height);\n }\n\n #toc {\n top: calc(var(--layout-banner-height) + var(--toc-bar-height));\n width: 100%;\n height: 100%;\n left: 0;\n background-color: var(--body-background-color);\n z-index: 10000;\n }\n\n body.show-toc #toc {\n display: block;\n }\n}\n","/*\n * Copyright 2021 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndiv.codetools {\n --button-width: 28px;\n --button-height: 24px;\n --arrow-size: 5px;\n display: flex;\n position: absolute;\n bottom: 9px;\n right: 8px;\n background: var(--codetools-background-color);\n padding: 0;\n border-radius: 2px;\n border: 1px solid var(--codetools-border-color);\n opacity: 0;\n transition: opacity 150ms ease-in-out;\n}\n\n.doc pre.highlight:hover div.codetools {\n opacity: 1;\n}\n\ndiv.codetools button {\n width: var(--button-width);\n height: var(--button-height);\n filter: var(--codetools-button-filter);\n background: no-repeat center / 16px 16px;\n border: none;\n padding: 0;\n outline: none;\n}\n\ndiv.codetools button:not(:last-child) {\n border-right: 1px solid var(--codetools-divider-color);\n}\n\ndiv.codetools button:hover {\n background-color: var(--codetools-hover-background-color);\n transition: filter 300ms;\n}\n\ndiv.codetools button:active {\n filter: var(--codetools-button-active-filter);\n transition: filter none;\n}\n\ndiv.codetools button span.label {\n display: none;\n}\n\ndiv.codetools button.copy-button {\n background-image: url(\"../img/octicons-16.svg#view-clippy\");\n}\n\ndiv.codetools button.unfold-button {\n background-image: url(\"../img/octicons-16.svg#view-unfold\");\n}\n\ndiv.codetools button.fold-button {\n background-image: url(\"../img/octicons-16.svg#view-fold\");\n}\n\ndiv.codetools span.copied {\n opacity: 0;\n display: block;\n content: \"\";\n position: relative;\n width: var(--button-width);\n height: var(--button-height);\n z-index: 1000000;\n transition: opacity 500ms;\n}\n\ndiv.codetools button:active span.copied {\n filter: invert();\n transition: filter none;\n}\n\ndiv.codetools span.copied:before {\n position: absolute;\n bottom: calc(var(--arrow-size) * -1);\n left: 50%;\n margin-left: calc(var(--arrow-size) / -2);\n content: \"\";\n border: var(--arrow-size) solid var(--codetools-popup-background-color);\n border-color: transparent transparent var(--codetools-popup-background-color)\n transparent;\n}\n\ndiv.codetools span.copied:after {\n content: \"Copied to clipboard!\";\n position: absolute;\n top: calc(var(--button-height) + var(--arrow-size));\n right: 100%;\n margin-right: calc(var(--button-width) * -1);\n background-color: var(--codetools-popup-background-color);\n color: var(--codetools-popup-font-color);\n padding: 5px 8px;\n border-radius: 3px;\n font-weight: bold;\n}\n\ndiv.codetools button.clicked span.copied {\n opacity: 1;\n}\n\nspan.fold-block {\n position: relative;\n float: left;\n clear: left;\n padding-right: 0.75rem;\n overflow: hidden;\n}\n\ncode.unfolded span.fold-block.hide-when-folded,\ncode:not(.unfolded) span.fold-block.hide-when-unfolded {\n max-height: 99999px;\n opacity: 1;\n}\n\ncode.unfolded span.fold-block.hide-when-unfolded,\ncode:not(.unfolded) span.fold-block.hide-when-folded {\n max-height: 0px;\n opacity: 0;\n}\n\ncode.unfolding span.fold-block.hide-when-folded {\n max-height: 600px;\n opacity: 1;\n}\n\ncode.folding span.fold-block.hide-when-unfolded {\n max-height: 400px;\n opacity: 1;\n}\n\ncode.unfolding span.fold-block.hide-when-unfolded,\ncode.folding span.fold-block.hide-when-folded {\n max-height: 0;\n opacity: 0;\n}\n\ncode.unfolding span.fold-block.hide-when-unfolded {\n transition: max-height 200ms cubic-bezier(0, 1, 0, 1), opacity 200ms linear;\n}\n\ncode.folding span.fold-block.hide-when-unfolded {\n transition: max-height 200ms cubic-bezier(1, 0, 1, 0), opacity 200ms linear;\n}\n\ncode.unfolding span.fold-block.hide-when-folded {\n transition: max-height 200ms cubic-bezier(1, 0, 1, 0), opacity 200ms linear;\n}\n\ncode.folding span.fold-block.hide-when-folded {\n transition: max-height 200ms cubic-bezier(0, 1, 0, 1), opacity 200ms linear;\n}\n"]} \ No newline at end of file diff --git a/docs/v4/demos.html b/docs/v4/demos.html new file mode 100644 index 0000000..e33029d --- /dev/null +++ b/docs/v4/demos.html @@ -0,0 +1,101 @@ + + + + + + + +Springdoc-openapi Demos + + + + + + +
      +
      +
      + + + +
      +
      +
      + + \ No newline at end of file diff --git a/docs/v4/faq.html b/docs/v4/faq.html new file mode 100644 index 0000000..bf7b21f --- /dev/null +++ b/docs/v4/faq.html @@ -0,0 +1,2091 @@ + + + + + + + +F.A.Q + + + + + + +
      +
      +
      + +
      +
      +

      F.A.Q

      +
      +
      +

      How can I define multiple OpenAPI definitions in one Spring Boot project?

      +
      +

      You can define your own groups of API based on the combination of: API paths and packages to scan. Each group should have a unique groupName. +The OpenAPI description of this group, will be available by default on:

      +
      +
      +
        +
      • +

        http://server:port/context-path/v3/api-docs/groupName

        +
      • +
      +
      +
      +

      To enable the support of multiple OpenAPI definitions, a bean of type GroupedOpenApi needs to be defined.

      +
      +
      +

      For the following Group definition(based on package path), the OpenAPI description URL will be : /v3/api-docs/stores

      +
      +
      +
      +
      @Bean
      +public GroupedOpenApi storeOpenApi() {
      +   String paths[] = {"/store/**"};
      +   return GroupedOpenApi.builder().group("stores").pathsToMatch(paths)
      +         .build();
      +}
      +
      +
      +
      +
      +

      For the following Group definition (based on package name), the OpenAPI description URL will be: /v3/api-docs/users

      +
      +
      +
      +
      @Bean
      +public GroupedOpenApi userOpenApi() {
      +   String packagesToscan[] = {"test.org.springdoc.api.app68.api.user"};
      +   return GroupedOpenApi.builder().group("users").packagesToScan(packagesToscan)
      +         .build();
      +}
      +
      +
      +
      +
      +

      For the following Group definition(based on path), the OpenAPI description URL will be: /v3/api-docs/pets

      +
      +
      +
      +
      @Bean
      +public GroupedOpenApi petOpenApi() {
      +   String paths[] = {"/pet/**"};
      +   return GroupedOpenApi.builder().group("pets").pathsToMatch(paths)
      +         .build();
      +}
      +
      +
      +
      +
      +

      For the following Group definition (based on package name and path), the OpenAPI description URL will be: /v3/api-docs/groups

      +
      +
      +
      +
      @Bean
      +public GroupedOpenApi groupOpenApi() {
      +   String paths[] = {"/v1/**"};
      +   String packagesToscan[] = {"test.org.springdoc.api.app68.api.user", "test.org.springdoc.api.app68.api.store"};
      +   return GroupedOpenApi.builder().group("groups").pathsToMatch(paths).packagesToScan(packagesToscan)
      +         .build();
      +}
      +
      +
      +
      +
      +

      For more details about the usage, you can have a look at the following sample Test:

      +
      + +
      +
      +

      How can I configure Swagger UI?

      +
      +
        +
      • +

        The support of the swagger official properties is available on springdoc-openapi. See Official documentation.

        +
      • +
      • +

        You can use the same swagger properties in the documentation as Spring Boot properties.

        +
      • +
      +
      +
      + + + + + +
      + + +All these properties should be declared with the following prefix: springdoc.swagger-ui +
      +
      +
      +
      +

      How can I filter the resources documented in the output specification by the provided group?

      +
      +
        +
      • +

        You can use the standard swagger-ui property filter.

        +
      • +
      +
      +
      +
      +
      springdoc.swagger-ui.filter=group-a
      +
      +
      +
      +
      +

      How can I disable/enable Swagger UI generation based on env variable?

      +
      +
        +
      • +

        This property helps you disable only the UI.

        +
      • +
      +
      +
      +
      +
      springdoc.swagger-ui.enabled=false
      +
      +
      +
      +
      +

      How can I control the default expansion setting for the operations and tags, in the Swagger UI ,

      +
      +
        +
      • +

        You can set this property in your application.yml like so for example:

        +
      • +
      +
      +
      +
      +
      springdoc.swagger-ui.doc-expansion= none
      +
      +
      +
      +
      +

      How can I change the layout of the swagger-ui?

      +
      +
        +
      • +

        For layout options, you can use swagger-ui configuration options. For example:

        +
      • +
      +
      +
      +
      +
      springdoc.swagger-ui.layout=BaseLayout
      +
      +
      +
      +
      +

      How can I sort endpoints alphabetically?

      +
      +
        +
      • +

        You can use the following springdoc-openapi properties:

        +
      • +
      +
      +
      +
      +
      #For sorting endpoints alphabetically
      +springdoc.swagger-ui.operationsSorter=alpha
      +#For sorting tags alphabetically
      +springdoc.swagger-ui.tagsSorter=alpha
      +
      +
      +
      +
      +

      How can I disable the try it out button?

      +
      +
        +
      • +

        You have to set the following property:

        +
      • +
      +
      +
      +
      +
      springdoc.swagger-ui.supportedSubmitMethods=get, put, post, delete, options, head, patch, trace
      +
      +
      +
      +
      +

      How can I add Reusable Enums ?

      +
      +
        +
      • +

        You should add @Schema(enumAsRef = true) on your enum.

        +
      • +
      +
      +
      +
      +

      How can i apply enumAsRef = true to all enums ?

      +
      +
        +
      • +

        Declare the following property:

        +
      • +
      +
      +
      +
      +
      static {
      +    io.swagger.v3.core.jackson.ModelResolver.enumsAsRef = true;
      +}
      +
      +
      +
      +
      +

      How can I explicitly set which paths to filter?

      +
      +
        +
      • +

        You can set list of paths to include using the following property:

        +
      • +
      +
      +
      +
      +
      springdoc.pathsToMatch=/v1, /api/balance/**
      +
      +
      +
      +
      +

      How can I explicitly set which packages to scan?

      +
      +
        +
      • +

        You can set list of packages to include using the following property:

        +
      • +
      +
      +
      +
      +
      springdoc.packagesToScan=package1, package2
      +
      +
      +
      +
      +

      How can I set Swagger properties programmatically?

      +
      +

      These can be set by creating a swaggerUiConfig bean as follows:

      +
      +
      +
      +
      @Bean
      +@Primary
      +fun swaggerUiConfig(config: SwaggerUiConfigProperties): SwaggerUiConfigProperties {
      +    config.showCommonExtensions = true
      +    config.queryConfigEnabled = true
      +    return config
      +}
      +
      +
      +
      +
      +
      +

      How can I ignore some field of model ?

      +
      +
        +
      • +

        You can use the following annotation on the top of the field that you want to hide:

        +
      • +
      • +

        @Schema(hidden = true)

        +
      • +
      +
      +
      +
      +

      How can I ignore @AuthenticationPrincipal parameter from spring-security ?

      +
      +
        +
      • +

        A solution workaround would be to use: @Parameter(hidden = true)

        +
      • +
      • +

        The projects that use spring-boot-starter-security or spring-security-oauth2-authorization-server should use:

        +
        +
          +
        • +

          springdoc-openapi-starter-webmvc-api if they depend on spring-boot-starter-web and they only need the access to the OpenAPI endpoints.

          +
        • +
        • +

          OR springdoc-openapi-starter-webmvc-ui, if they depend on spring-boot-starter-web and they also need the access to the swagger-ui.

          +
        • +
        • +

          OR springdoc-openapi-starter-webflux-api if they depend on spring-boot-starter-webflux and they only the access to the OpenAPI endpoints.

          +
        • +
        • +

          OR springdoc-openapi-starter-webflux-ui, if they depend on spring-boot-starter-webflux and they also need the access to the swagger-ui.

          +
        • +
        +
        +
      • +
      +
      +
      +
      +

      Is there a Gradle plugin available?

      +
      +
        +
      • +

        Yes. More details are available, in the gradle plugin section.

        +
      • +
      +
      +
      +
      +

      How can I hide a parameter from the documentation ?

      +
      +
        +
      • +

        You can use @Parameter(hidden = true)

        +
      • +
      +
      +
      +
      +

      Is @Parameters annotation supported ?

      +
      +
        +
      • +

        Yes

        +
      • +
      +
      +
      +
      +

      Does springdoc-openapi support Jersey?

      +
      + +
      +
      +
      +

      Can springdoc-openapi generate API only for @RestController?

      +
      +
        +
      • +

        @RestController is equivalent to @Controller + @RequestMapping on the type level.

        +
      • +
      • +

        For some legacy apps, we are constrained to still support both.

        +
      • +
      • +

        If you need to hide the @Controller on the type level, in this case, you can use: @Hidden on controller level.

        +
      • +
      • +

        Please note this annotation can be also used to hide some methods from the generated documentation.

        +
      • +
      +
      +
      +
      +

      Are the following validation annotations supported : @NotEmpty @NotBlank @PositiveOrZero @NegativeOrZero?

      +
      +
        +
      • +

        Yes

        +
      • +
      +
      +
      +
      +

      How can I map Pageable (spring-data-commons) object to correct URL-Parameter in Swagger UI?

      +
      +

      The support for Pageable of spring-data-commons is available out-of-the box since springdoc-openapi v1.6.0. +For this, you have to combine @ParameterObject annotation with the Pageable type.

      +
      +
      +

      Before springdoc-openapi v1.6.0:

      +
      +
      +
        +
      • +

        You can use as well @ParameterObject instead of @PageableAsQueryParam for HTTP GET methods.

        +
      • +
      +
      +
      +
      +
      static {
      +    getConfig().replaceParameterObjectWithClass(org.springframework.data.domain.Pageable.class, Pageable.class)
      +            .replaceParameterObjectWithClass(org.springframework.data.domain.PageRequest.class, Pageable.class);
      +}
      +
      +
      +
      +
      +
        +
      • +

        Another solution, is to configure Pageable manually:

        +
        +
          +
        • +

          you will have to declare the explicit mapping of Pageable fields as Query Params and add the @Parameter(hidden = true) Pageable pageable on your pageable parameter.

          +
        • +
        • +

          You should also, declare the annotation @PageableAsQueryParam provided by springdoc-openapi on the method level, or declare your own if need to define your custom description, defaultValue, …​

          +
        • +
        +
        +
      • +
      +
      +
      +

      If you want to disable the support of spring Pageable Type, you can use:

      +
      +
      +
      +
      springdoc.model-converters.pageable-converter.enabled=false
      +
      +
      +
      + + + + + +
      + + +The property springdoc.model-converters.pageable-converter.enabled is only available since v1.5.11+ +
      +
      +
      +
      +

      How can I generate enums in the generated description?

      +
      +
        +
      • +

        You could add a property allowableValues, to @Parameter. For example:

        +
      • +
      +
      +
      +
      +
      @GetMapping("/example")
      +public Object example(@Parameter(name ="json", schema = @Schema(description = "var 1",type = "string", allowableValues = {"1", "2"}))
      +String json) {
      +   return null;
      +}
      +
      +
      +
      +
      +
        +
      • +

        or you could override toString on your enum:

        +
      • +
      +
      +
      +
      +
      @Override
      +@JsonValue
      +public String toString() {
      +   return String.valueOf(action);
      +}
      +
      +
      +
      +
      +
      +

      How can I deploy springdoc-openapi-starter-webmvc-ui behind a reverse proxy?

      +
      +
        +
      • +

        If your application is running behind a proxy, a load-balancer or in the cloud, the request information (like the host, port, scheme…​) might change along the way. Your application may be running on 10.10.10.10:8080, but HTTP clients should only see example.org.

        +
      • +
      • +

        RFC7239 "Forwarded Headers" defines the Forwarded HTTP header; proxies can use this header to provide information about the original request. You can configure your application to read those headers and automatically use that information when creating links and sending them to clients in HTTP 302 responses, JSON documents or HTML pages. There are also non-standard headers, like X-Forwarded-Host, X-Forwarded-Port, X-Forwarded-Proto, X-Forwarded-Ssl, and X-Forwarded-Prefix.

        +
      • +
      • +

        If the proxy adds the commonly used X-Forwarded-For and X-Forwarded-Proto headers, setting server.forward-headers-strategy to NATIVE is enough to support those. With this option, the Web servers themselves natively support this feature; you can check their specific documentation to learn about specific behavior.

        +
      • +
      • +

        You need to make sure the following header is set in your reverse proxy configuration: X-Forwarded-Prefix

        +
      • +
      • +

        For example, using Apache 2, configuration:

        +
      • +
      +
      +
      +
      +
      RequestHeader set X-Forwarded-Prefix "/custom-path"
      +
      +
      +
      +
        +
      • +

        Then, in your Spring Boot application make sure your application handles this header: X-Forwarded-For. There are two ways to achieve this:

        +
      • +
      +
      +
      +
      +
      server.use-forward-headers=true
      +
      +
      +
      +
        +
      • +

        If this is not enough, Spring Framework provides a ForwardedHeaderFilter. You can register it as a Servlet Filter in your application by setting server.forward-headers-strategy is set to FRAMEWORK.

        +
      • +
      • +

        Since Spring Boot 2.2, this is the new property to handle reverse proxy headers:

        +
      • +
      +
      +
      +
      +
      server.forward-headers-strategy=framework
      +
      +
      +
      +
        +
      • +

        And you can add the following bean to your application:

        +
      • +
      +
      +
      +
      +
      @Bean
      +ForwardedHeaderFilter forwardedHeaderFilter() {
      +   return new ForwardedHeaderFilter();
      +}
      +
      +
      +
      +
      +
        +
      • +

        If you need to manually adjust the URL displayed in the Swagger UI, implement the ServerBaseUrlCustomizer interface. This might be necessary to remove the port number, for example.

        +
      • +
      +
      +
      +
      +
      @Bean
      +public class CustomServerBaseUrlCustomizer implements ServerBaseUrlCustomizer {
      +    @Override
      +    public String customize(String serverBaseUrl) {
      +        try {
      +            URL url = new URL(serverBaseUrl);
      +            if (url.getHost().contains(".com")) {
      +                serverBaseUrl = new URL(url.getProtocol(),url.getHost(),url.getFile()).toString();
      +            }
      +        } catch (MalformedURLException ex) {
      +            // nothing we can do
      +        }
      +
      +        return serverBaseUrl;
      +    }
      +}
      +
      +
      +
      +
      +
      +

      Is @JsonView annotations in Spring MVC APIs supported?

      +
      +
        +
      • +

        Yes

        +
      • +
      +
      +
      +
      +

      Adding springdoc-openapi-starter-webmvc-ui dependency breaks my public/index.html welcome page

      +
      +
        +
      • +

        If you already have static content on your root, and you don’t want it to be overridden by springdoc-openapi-starter-webmvc-ui configuration, you can just define a custom configuration of the swagger-ui, in order not to override the configuration of your files from in your context-root:

        +
      • +
      • +

        For example use:

        +
      • +
      +
      +
      +
      +
      springdoc.swagger-ui.path= /swagger-ui/api-docs.html
      +
      +
      +
      +
      +

      How can I test the Swagger UI?

      + +
      +
      +

      How can I customise the OpenAPI object ?

      +
      + +
      +
      +
      +
      @Bean
      +public OpenApiCustomizer consumerTypeHeaderOpenAPICustomizer() {
      +return openApi -> openApi.getPaths().values().stream().flatMap(pathItem -> pathItem.readOperations().stream())
      +    .forEach(operation -> operation.addParametersItem(new HeaderParameter().$ref("#/components/parameters/myConsumerTypeHeader")));
      +}
      +
      +
      +
      +
      + + + + + +
      + + +This bean OpenApiCustomizer will be applied to the Default OpenAPI only. +
      +
      +
      +

      If you need the OpenApiCustomizer to applied to GroupedOpenApi as well, then use GlobalOpenApiCustomizer instead.

      +
      +
      +
      +

      How can I return an empty content as response?

      +
      +
        +
      • +

        It is be possible to handle as return an empty content as response using, one of the following syntaxes:

        +
      • +
      • +

        content = @Content

        +
      • +
      • +

        content = @Content(schema = @Schema(hidden = true))

        +
      • +
      • +

        For example:

        +
      • +
      +
      +
      +
      +
      @Operation(summary = "Get thing", responses = {
      +      @ApiResponse(description = "Successful Operation", responseCode = "200", content = @Content(mediaType = "application/json", schema = @Schema(implementation = String.class))),
      +      @ApiResponse(responseCode = "404", description = "Not found", content = @Content),
      +      @ApiResponse(responseCode = "401", description = "Authentication Failure", content = @Content(schema = @Schema(hidden = true))) })
      +@RequestMapping(path = "/testme", method = RequestMethod.GET)
      +ResponseEntity<String> testme() {
      +   return ResponseEntity.ok("Hello");
      +}
      +
      +
      +
      +
      +
      +

      How are endpoints with multiple consuming media types supported?

      +
      +
        +
      • +

        An overloaded method on the same class, with the same HTTP Method and path, will have as a result, only one OpenAPI Operation generated.

        +
      • +
      • +

        In addition, it’s recommended to have the @Operation in the level of one of the overloaded methods. Otherwise it might be overridden if it’s declared many times within the same overloaded method.

        +
      • +
      +
      +
      +
      +

      How can I get yaml and json (OpenAPI) in compile time?

      +
      + +
      +
      +
      +

      What are the ignored types in the documentation?

      +
      + +
      +
      +
      +

      How can i disable ignored types:

      +
      +

      If you don’t want to ignore the types Principal, Locale, HttpServletRequest, and others,:

      +
      +
      +
      +
      SpringDocUtils.getConfig().removeRequestWrapperToIgnore(HttpServletRequest.class)
      +
      +
      +
      +
      +
      +

      How do I add authorization header in requests?

      +
      +
        +
      • +

        You should add the @SecurityRequirement tags to your protected APIs.

        +
      • +
      • +

        For example:

        +
      • +
      +
      +
      +
      +
      @Operation(security = { @SecurityRequirement(name = "bearer-key") })
      +
      +
      +
      +
        +
      • +

        And the security definition sample:

        +
      • +
      +
      +
      +
      +
      @Bean
      + public OpenAPI customOpenAPI() {
      +   return new OpenAPI()
      +          .components(new Components()
      +          .addSecuritySchemes("bearer-key",
      +          new SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("bearer").bearerFormat("JWT")));
      +}
      +
      +
      +
      +
      +
      +

      Differentiation to Springfox project

      +
      +
        +
      • +

        OAS 3 was released in July 2017, and there was no release of springfox to support OAS 3. +springfox covers for the moment only swagger 2 integration with Spring Boot. The latest release date is June 2018. So, in terms of maintenance there is a big lack of support lately.

        +
      • +
      • +

        We decided to move forward and share the library that we already used on our internal projects, with the community.

        +
      • +
      • +

        The biggest difference with springfox, is that we integrate new features not covered by springfox:

        +
      • +
      • +

        The integration between Spring Boot and OpenAPI 3 standard.

        +
      • +
      • +

        We rely on on swagger-annotations and swagger-ui only official libraries.

        +
      • +
      • +

        We support new features on Spring 5, like spring-webflux with annotated and functional style.

        +
      • +
      • +

        We do our best to answer all the questions and address all issues or enhancement requests

        +
      • +
      +
      +
      +
      +

      How do I migrate to OpenAPI 3 with springdoc-openapi

      +
      +
        +
      • +

        There is no relation between springdoc-openapi and springfox.If you want to migrate to OpenAPI 3:

        +
      • +
      • +

        Remove all the dependencies and the related code to springfox

        +
      • +
      • +

        Add springdoc-openapi-starter-webmvc-ui dependency

        +
      • +
      • +

        If you don’t want to serve the UI from your root path or there is a conflict with an existing configuration, you can just change the following property:

        +
      • +
      +
      +
      +
      +
      springdoc.swagger-ui.path=/you-path/swagger-ui.html
      +
      +
      +
      +
      +

      How can I set a global header?

      +
      +
        +
      • +

        You may have global parameters with Standard OpenAPI description.

        +
      • +
      • +

        If you need the definitions to appear globally (within every group), no matter if the group fulfills the conditions specified on the GroupedOpenApi , you can use OpenAPI Bean.

        +
      • +
      • +

        You can define common parameters under parameters in the global components section and reference them elsewhere via $ref. You can also define global header parameters.

        +
      • +
      • +

        For this, you can override to OpenAPI Bean, and set the global headers or parameters definition on the components level.

        +
      • +
      +
      +
      +
      +
      @Bean
      +public OpenAPI customOpenAPI(@Value("${springdoc.version}") String appVersion) {
      + return new OpenAPI()
      +        .components(new Components().addSecuritySchemes("basicScheme", new SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("basic"))
      +        .addParameters("myHeader1", new Parameter().in("header").schema(new StringSchema()).name("myHeader1")).addHeaders("myHeader2", new Header().description("myHeader2 header").schema(new StringSchema())))
      +        .info(new Info()
      +        .title("Petstore API")
      +        .version(appVersion)
      +        .description("This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.")
      +        .termsOfService("http://swagger.io/terms/")
      +        .license(new License().name("Apache 2.0").url("http://springdoc.org")));
      +}
      +
      +
      +
      +
      +
      +

      Are Callbacks supported?

      +
      +
        +
      • +

        Yes

        +
      • +
      +
      +
      +
      +

      How can I define SecurityScheme ?

      +
      +
        +
      • +

        You can use: @SecurityScheme annotation.

        +
      • +
      • +

        Or you can define it programmatically, by overriding OpenAPI Bean:

        +
      • +
      +
      +
      +
      +
       @Bean
      + public OpenAPI customOpenAPI(@Value("${springdoc.version}") String appVersion) {
      +  return new OpenAPI()
      +   .components(new Components().addSecuritySchemes("basicScheme",
      +   new SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("basic")))
      +   info(new Info().title("SpringShop API").version(appVersion)
      +   .license(new License().name("Apache 2.0").url("http://springdoc.org")));
      + }
      +
      +
      +
      +
      +
      +

      How can I hide an operation or a controller from documentation ?

      +
      +
        +
      • +

        You can use @io.swagger.v3.oas.annotations.Hidden annotation at @RestController, @RestControllerAdvice and method level

        +
      • +
      • +

        The @Hidden annotation on exception handler methods, is considered when building generic (error) responses from @ControllerAdvice exception handlers.

        +
      • +
      • +

        Or use: @Operation(hidden = true)

        +
      • +
      +
      +
      +
      +

      How to configure global security schemes?

      +
      +
        +
      • +

        For global SecurityScheme, you can add it inside your own OpenAPI definition:

        +
      • +
      +
      +
      +
      +
      @Bean
      +public OpenAPI customOpenAPI() {
      +    return new OpenAPI().components(new Components()
      +    .addSecuritySchemes("basicScheme", new SecurityScheme()
      +    .type(SecurityScheme.Type.HTTP).scheme("basic"))).info(new Info().title("Custom API")
      +    .version("100")).addTagsItem(new Tag().name("mytag"));
      +}
      +
      +
      +
      +
      +
      +

      Can I use spring property with swagger annotations?

      +
      +
        +
      • +

        The support of spring property resolver for @Info: title * description * version * termsOfService

        +
      • +
      • +

        The support of spring property resolver for @Info.license: name * url

        +
      • +
      • +

        The support of spring property resolver for @Info.contact: name * email * url

        +
      • +
      • +

        The support of spring property resolver for @Operation: description * summary

        +
      • +
      • +

        The support of spring property resolver for @Parameter: description * name

        +
      • +
      • +

        The support of spring property resolver for @ApiResponse: description

        +
      • +
      • +

        Its also possible to declare security URLs for @OAuthFlow: openIdConnectUrl * authorizationUrl * refreshUrl * tokenUrl

        +
      • +
      • +

        The support of spring property resolver for @Schema: name * title * description , by setting springdoc.api-docs.resolve-schema-properties to true

        +
      • +
      • +

        The support of spring property resolver for @ExtensionProperty by setting springdoc.api-docs.resolve-extensions-properties to true

        +
      • +
      +
      +
      +
      +

      How is server URL generated ?

      +
      +
        +
      • +

        Generating automatically server URL may be useful, if the documentation is not present.

        +
      • +
      • +

        If the server annotations are present, they will be used instead.

        +
      • +
      +
      +
      +
      +

      How can I disable springdoc-openapi cache?

      +
      +
        +
      • +

        By default, the OpenAPI description is calculated once, and then cached.

        +
      • +
      • +

        Sometimes the same swagger-ui is served behind internal and external proxies. some users want the server URL, to be computed on each http request.

        +
      • +
      • +

        In order to disable springdoc cache, you will have to set the following property:

        +
      • +
      +
      +
      +
      +
      springdoc.cache.disabled= true
      +
      +
      +
      +
      +

      How can I expose the mvc api-docs endpoints without using the swagger-ui?

      +
      +
        +
      • +

        You should use the springdoc-openapi-core dependency only:

        +
      • +
      +
      +
      +
      +
      <dependency>
      +  <groupId>org.springdoc</groupId>
      +  <artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
      +  <version>latest.version</version>
      +</dependency>
      +
      +
      +
      +
      +

      How can I disable springdoc-openapi endpoints ?

      +
      +
        +
      • +

        Use the following property:

        +
      • +
      +
      +
      +
      +
      springdoc.api-docs.enabled=false
      +
      +
      +
      +
      +

      How can I hide Schema of the the response ?

      +
      +
        +
      • +

        To hide the response element, using @Schema annotation, as follows, at operation level:

        +
      • +
      +
      +
      +
      +
      @Operation(responses = @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(hidden = true))))
      +
      +
      +
      +
        +
      • +

        Or directly at @ApiResponses level:

        +
      • +
      +
      +
      +
      +
      @ApiResponses(value = {@ApiResponse(responseCode = "200", content = @Content(schema = @Schema(hidden = true))) })
      +OR
      +@ApiResponse(responseCode = "404", description = "Not found", content = @Content)
      +
      +
      +
      +
      +

      What is the URL of the swagger-ui, when I set a different context-path?

      +
      +
        +
      • +

        If you use different context-path:

        +
      • +
      +
      +
      +
      +
      server.servlet.context-path= /foo
      +
      +
      +
      +
        +
      • +

        The swagger-ui will be available on the following URL:

        +
        +
          +
        • +

          http://server:port/foo/swagger-ui.html

          +
        • +
        +
        +
      • +
      +
      +
      +
      +

      Can I customize OpenAPI object programmatically?

      +
      +
        +
      • +

        You can Define your own OpenAPI Bean: If you need the definitions to appear globally (within every group), no matter if the group fulfills the conditions specified on the GroupedOpenApi , you can use OpenAPI Bean.

        +
      • +
      +
      +
      +
      +
      @Bean
      +public OpenAPI customOpenAPI(@Value("${springdoc.version}") String appVersion) {
      +   return new OpenAPI()
      +    .components(new Components().addSecuritySchemes("basicScheme",
      +            new SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("basic")))
      +    .info(new Info().title("SpringShop API").version(appVersion)
      +            .license(new License().name("Apache 2.0").url("http://springdoc.org")));
      +}
      +
      +
      +
      +
      +
        +
      • +

        If you need the definitions to appear within a specific group, and respect the conditions specified on the GroupedOpenApi, you can add OpenApiCustomizer to your GroupedOpenApi definition.

        +
      • +
      +
      +
      +
      +
      GroupedOpenApi.builder().group("users").pathsToMatch(paths).packagesToScan(packagedToMatch).addOpenApiCustomizer(customerGlobalHeaderOpenApiCustomizer())
      +                .build()
      +
      +@Bean
      +public OpenApiCustomizer customerGlobalHeaderOpenApiCustomizer() {
      +   return openApi -> openApi.path("/foo",
      +   new PathItem().get(new Operation().operationId("foo").responses(new ApiResponses()
      +   .addApiResponse("default",new ApiResponse().description("")
      +   .content(new Content().addMediaType("fatz", new MediaType()))))));
      +}
      +
      +
      +
      +
      +
      +

      Where can I find the source code of the demo applications?

      +
      + +
      +
      +
      +

      Does this library supports annotations from interfaces?

      +
      +
        +
      • +

        Yes

        +
      • +
      +
      +
      +
      +

      What is the list of the excluded parameter types?

      + +
      +
      +

      Is file upload supported ?

      +
      +
        +
      • +

        The library supports the main file types: MultipartFile, @RequestPart, FilePart

        +
      • +
      • +

        You can upload a file as follows:

        +
      • +
      +
      +
      +
      +
      import io.swagger.v3.oas.annotations.Parameter;
      +import io.swagger.v3.oas.annotations.media.Content;
      +import io.swagger.v3.oas.annotations.media.Encoding;
      +import io.swagger.v3.oas.annotations.parameters.RequestBody;
      +
      +@PostMapping(value = "/upload", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
      +public ResponseEntity<?> upload(@Parameter(description = "file") final MultipartFile file) {
      +    return null;
      +}
      +
      +@PostMapping(value = "/uploadFileWithQuery", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
      +public ResponseEntity<?> uploadFileWithQuery(@Parameter(description = "file") @RequestPart("file") final MultipartFile file,
      +        @Parameter(description = "An extra query parameter") @RequestParam String name) {
      +    return null;
      +}
      +
      +@PostMapping(value = "/uploadFileWithJson", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}, produces = {
      +        MediaType.APPLICATION_JSON_VALUE})
      +public ResponseEntity<?> uploadFileWithJson(
      +        @RequestBody(content = @Content(encoding = @Encoding(name = "jsonRequest", contentType = MediaType.APPLICATION_JSON_VALUE)))
      +        @Parameter(description = "An extra JSON payload sent with file") @RequestPart("jsonRequest") final JsonRequest jsonRequest,
      +        @RequestPart("file") final MultipartFile file) {
      +    return null;
      +}
      +
      +
      +
      +
      +
      +

      Can I use @Parameter inside @Operation annotation?

      +
      +
        +
      • +

        Yes, it’s supported

        +
      • +
      +
      +
      +
      +

      Why my parameter is marked as required?

      +
      +
        +
      • +

        Any @GetMapping parameters is marked as required, even if @RequestParam is missing.

        +
      • +
      • +

        You can add @Parameter(required=false) annotation if you need different behaviour.

        +
      • +
      • +

        Query parameters with defaultValue specified are marked as required.

        +
      • +
      +
      +
      +
      +

      How are overloaded methods with the same endpoints, but with different parameters

      +
      +
        +
      • +

        springdoc-openapi renders these methods as a single endpoint. It detects the overloaded endpoints, and generates parameters.schema.oneOf.

        +
      • +
      +
      +
      +
      +

      What is a proper way to set up Swagger UI to use provided spec.yml?

      +
      +
        +
      • +

        With this property, all the springdoc-openapi auto-configuration beans are disabled:

        +
      • +
      +
      +
      +
      +
      springdoc.api-docs.enabled=false
      +
      +
      +
      +
        +
      • +

        Then enable the minimal Beans configuration, by adding this Bean:

        +
      • +
      +
      +
      +
      +
      @Bean
      +SpringDocConfiguration springDocConfiguration(){
      +   return new SpringDocConfiguration();
      +}
      +
      +@Bean
      +SpringDocConfigProperties springDocConfigProperties() {
      +   return new SpringDocConfigProperties();
      +}
      +
      +@Bean
      +ObjectMapperProvider objectMapperProvider(SpringDocConfigProperties springDocConfigProperties){
      +    return new ObjectMapperProvider(springDocConfigProperties);
      +}
      +
      +
      +
      +
      +
        +
      • +

        Then configure, the path of your custom UI yaml file.

        +
      • +
      +
      +
      +
      +
      springdoc.swagger-ui.url=/api-docs.yaml
      +
      +
      +
      +
      +

      Is there a way to send authorization header through the @Parameter tag?

      +
      + +
      +
      +
      +

      My Rest Controller using @Controller annotation is ignored?

      +
      +
        +
      • +

        This is the default behaviour if your @Controller doesn’t have annotation @ResponseBody

        +
      • +
      • +

        You can change your controllers to @RestControllers. Or add @ResponseBody + @Controller.

        +
      • +
      • +

        If its not possible, you can configure springdoc to scan you additional controller using SpringDocUtils. For example:

        +
      • +
      +
      +
      +
      +
      static {
      +   SpringDocUtils.getConfig().addRestControllers(HelloController.class);
      +}
      +
      +
      +
      +
      +
      +

      How can I define groups using application.yml?

      +
      +
        +
      • +

        You can load groups dynamically using spring-boot configuration files.

        +
      • +
      • +

        Note that, for this usage, you don’t have to declare the GroupedOpenApi Bean.

        +
      • +
      • +

        You need to declare the following properties, under the prefix springdoc.group-configs.

        +
      • +
      • +

        For example:

        +
      • +
      +
      +
      +
      +
      springdoc.group-configs[0].group=users
      +springdoc.group-configs[0].paths-to-match=/user/**
      +springdoc.group-configs[0].packages-to-scan=test.org.springdoc.api
      +
      +
      +
      + +
      +
      +
      +

      How can I extract fields from parameter object ?

      +
      +
        +
      • +

        You can use springdoc annotation @ParameterObject.

        +
      • +
      • +

        Request parameter annotated with @ParameterObject will help adding each field of the parameter as a separate request parameter.

        +
      • +
      • +

        This is compatible with Spring MVC request parameters mapping to POJO object.

        +
      • +
      • +

        This annotation does not support nested parameter objects.

        +
      • +
      • +

        POJO object must contain getters for fields with mandatory prefix get. Otherwise, the swagger documentation will not show the fields of the annotated entity.

        +
      • +
      +
      +
      +
      +

      How can I use the last springdoc-openapi SNAPSHOT ?

      +
      +
        +
      • +

        For testing purposes only, you can test temporarily using the last springdoc-openapi SNAPSHOT

        +
      • +
      • +

        To achieve that, configure your pom.xml file with the following <repositories> section:

        +
      • +
      +
      +
      +
      +
          <repositories>
      +      <repository>
      +        <name>Central Portal Snapshots</name>
      +        <id>central-portal-snapshots</id>
      +        <url>https://central.sonatype.com/repository/maven-snapshots/</url>
      +        <releases>
      +          <enabled>false</enabled>
      +        </releases>
      +        <snapshots>
      +          <enabled>true</enabled>
      +        </snapshots>
      +      </repository>
      +    </repositories>
      +
      +
      +
      +
      +

      How can I use enable springdoc-openapi MonetaryAmount support ?

      +
      +
        +
      • +

        If an application wants to enable the springdoc-openapi support, it declares:

        +
      • +
      +
      +
      +
      +
      SpringDocUtils.getConfig().replaceWithClass(MonetaryAmount.class, org.springdoc.core.converters.models.MonetaryAmount.class);
      +
      +
      +
      +
      +
        +
      • +

        Another solution, without using springdoc-openapi MonetaryAmount, would be:

        +
      • +
      +
      +
      +
      +
      SpringDocUtils.getConfig().replaceWithSchema(MonetaryAmount.class, new ObjectSchema()
      +            .addProperties("amount", new NumberSchema()).example(99.96)
      +            .addProperties("currency", new StringSchema().example("USD")));
      +
      +
      +
      +
      +
      +

      How can i aggregate external endpoints (exposing OPENAPI 3 spec) inside one single application?

      +
      +

      The properties springdoc.swagger-ui.urls.*, are suitable to configure external (/v3/api-docs url). +For example if you want to agreagte all the endpoints of other services, inside one single application. +IMPORTANT: Don’t forget that CORS needs to be enabled as well.

      +
      +
      +
      +

      How can use custom json/yml file instead of generated one ?

      +
      +

      If your file open-api.json, contains the OpenAPI documentation in OpenAPI 3 format. +Then simply declare: The file name can be anything you want, from the moment your declaration is consistent yaml or json OpenAPI Spec.

      +
      +
      +
      +
         springdoc.swagger-ui.url=/open-api.json
      +
      +
      +
      +

      Then the file open-api.json, should be located in: src/main/resources/static +No additional configuration is needed.

      +
      +
      +
      +

      How can i enable CSRF support?

      +
      +

      If you are using standard headers.( For example using spring-security headers) +If the CSRF Token is required, swagger-ui automatically sends the new XSRF-TOKEN during each HTTP REQUEST.

      +
      +
      +

      If your XSRF-TOKEN isn’t standards-based, you can use a requestInterceptor to manually capture and attach the latest xsrf token to requests programmatically via spring resource transformer:

      +
      + +
      +

      Starting from release v1.4.4 of springdoc-openapi, a new property is added to enable CSRF support, while using standard header names:

      +
      +
      +
      +
      springdoc.swagger-ui.csrf.enabled=true
      +
      +
      +
      +
      +

      How can i disable the default swagger petstore URL?

      +
      +

      You can use the following property:

      +
      +
      +
      +
      springdoc.swagger-ui.disable-swagger-default-url=true
      +
      +
      +
      +
      +

      Is @PageableDefault supported, to enhance the OpenAPI 3 docuementation?

      +
      +

      Yes, you can use it in conjunction with @ParameterObject annotation. +Also, the spring-boot spring.data.web. and spring.data.rest.default. properties are supported since v1.4.5

      +
      +
      +
      +

      How can i make spring security login-endpoint visible ?

      +
      +

      You can use the following property:

      +
      +
      +
      +
      springdoc.show-login-endpoint=true
      +
      +
      +
      +
      +

      How can i show schema definitions even the schema is not referenced?

      +
      +

      You can use the following property:

      +
      +
      +
      +
      springdoc.remove-broken-reference-definitions=false
      +
      +
      +
      +
      +

      How to override @Deprecated?

      +
      +

      The whole idea of springdoc-openapi is to get your documentation the closest to the code, with minimal code changes. +If the code contains @Deprecated, sprindoc-openapi will consider its schema as Deprecated as well. +If you want to declare a field on swagger as non deprecated, even with the java code, the field contains @Depreacted, +You can use the following property that is available since release v1.4.3:

      +
      +
      +
      +
      springdoc.model-converters.deprecating-converter.enabled=false
      +
      +
      +
      +
      +

      How can i display a method that returns ModelAndView?

      +
      +

      You can use the following property:

      +
      +
      +
      +
      springdoc.model-and-view-allowed=true
      +
      +
      +
      +
      +

      How can i have pretty-printed output of the OpenApi specification?

      +
      +

      You can use the following property:

      +
      +
      +
      +
      springdoc.writer-with-default-pretty-printer=true
      +
      +
      +
      +
      +

      How can i define different schemas for the same class?

      +
      +

      Complex objects are always resolved as a reference to a schema defined in components. +For example let’s consider a Instance class with an workAddress and homeAddress attribute of type Address:

      +
      +
      +
      +
      public class PersonDTO {
      +
      +	@JsonProperty
      +	private String email;
      +
      +	@JsonProperty
      +	private String firstName;
      +
      +	@JsonProperty
      +	private String lastName;
      +
      +	@Schema(ref = "WorkAddressSchema")
      +	@JsonProperty
      +	private Address workAddress;
      +
      +	@Schema(ref = "HomeAddressSchema")
      +	@JsonProperty
      +	private Address homeAddress;
      +
      +}
      +
      +public class Address {
      +
      +	@JsonProperty
      +	private String addressName;
      +
      +}
      +
      +
      +
      +
      +

      If you want to define two different schemas for this class, you can set up 2 different schemas as follow:

      +
      +
      +
      +
      @Bean
      +public OpenAPI customOpenAPI() {
      +return new OpenAPI().components(new Components()
      +.addSchemas("WorkAddressSchema", getSchemaWithDifferentDescription(Address.class, "work Address" ))
      +.addSchemas("HomeAddressSchema", getSchemaWithDifferentDescription(Address.class, "home Address" )));
      +}
      +
      +private Schema getSchemaWithDifferentDescription(Class className, String description){
      +ResolvedSchema resolvedSchema = ModelConverters.getInstance()
      +.resolveAsResolvedSchema(
      +new AnnotatedType(className).resolveAsRef(false));
      +return resolvedSchema.schema.description(description);
      +}
      +
      +
      +
      +
      +
      +

      How can i define different description for a class attribute depending on usage?

      +
      +

      For example let’s consider a Instance class with an email attribute:

      +
      +
      +
      +
      public class PersonDTO {
      +
      +	@JsonProperty
      +	private String email;
      +
      +	@JsonProperty
      +	private String firstName;
      +
      +	@JsonProperty
      +	private String lastName;
      +
      +
      +}
      +
      +
      +
      +
      +

      If you want to define two different description for the email, you can set up 2 different schemas as follow:

      +
      +
      +
      +
      @Bean
      +public OpenAPI customOpenAPI() {
      +return new OpenAPI().components(new Components()
      +.addSchemas("PersonDTO1", getFieldSchemaWithDifferentDescription(PersonDTO.class, "work email" ))
      +.addSchemas("PersonDTO2", getFieldSchemaWithDifferentDescription(PersonDTO.class, "home email" )));
      +}
      +
      +private Schema getFieldSchemaWithDifferentDescription(Class className, String description){
      +    ResolvedSchema resolvedSchema = ModelConverters.getInstance()
      +            .resolveAsResolvedSchema(
      +                    new AnnotatedType(className).resolveAsRef(false));
      +    return resolvedSchema.schema.addProperties("email", new StringSchema().description(description));
      +}
      +
      +
      +
      +
      +
      +

      Customizing swagger static resources

      +
      +

      You can customize swagger documentation static resources located in META-INF/resources/webjars/swagger-ui/{swagger.version}/. The list of resources includes:

      +
      +
      +
        +
      • +

        index.html

        +
      • +
      • +

        swagger-ui-bundle.js

        +
      • +
      • +

        swagger-ui.css

        +
      • +
      • +

        swagger-ui-standalone-preset.js

        +
      • +
      • +

        swagger-ui.css.map

        +
      • +
      • +

        swagger-ui-bundle.js.map

        +
      • +
      • +

        swagger-ui-standalone-preset.js.map

        +
      • +
      • +

        favicon-32x32.png

        +
      • +
      +
      +
      +

      To do this, you need to extend the implementation of SwaggerIndexPageTransformer

      +
      +
      +
      +
      public class SwaggerCodeBlockTransformer
      +       extends SwaggerIndexPageTransformer {
      +  // < constructor >
      +  @Override
      +  public Resource transform(HttpServletRequest request,
      +                            Resource resource,
      +                            ResourceTransformerChain transformer)
      +                            throws IOException {
      +      if (resource.toString().contains("swagger-ui.css")) {
      +          final InputStream is = resource.getInputStream();
      +          final InputStreamReader isr = new InputStreamReader(is);
      +          try (BufferedReader br = new BufferedReader(isr)) {
      +              final String css = br.lines().collect(Collectors.joining());
      +              final byte[] transformedContent = css.replace("old", "new").getBytes();
      +              return  new TransformedResource(resource, transformedContent);
      +          } // AutoCloseable br > isr > is
      +      }
      +      return super.transform(request, resource, transformer);
      +  }
      +
      +}
      +
      +
      +
      +
      +

      Next, add transformer @Bean to your @Configuration

      +
      +
      +
      +
      @Configuration
      +public class OpenApiConfig {
      +    @Bean
      +    public SwaggerIndexTransformer swaggerIndexTransformer(
      +            SwaggerUiConfigProperties a,
      +            SwaggerUiOAuthProperties b,
      +            SwaggerUiConfigParameters c,
      +            SwaggerWelcomeCommon d) {
      +        return new SwaggerCodeBlockTransformer(a, b, c, d);
      +    }
      +}
      +
      +
      +
      +
      +

      Illustrative example

      +
      +
      +
      +Illustrative example +
      +
      +
      +
      +

      Is GraalVM supported ?

      +
      +

      The native support available added in spring-boot 3. +If you have some time, do not hesitate to test it before the next release.

      +
      +
      +

      For the OpenAPI REST endpoints, you just need to build your application with the spring native profile.

      +
      +
      +

      If you give @OpenAPIDefinition or @SecurityScheme to a class that has no implementation, that class will disappear when you natively compile. +To avoid this, give the class a @Configuration.

      +
      +
      +
      +
      @Configuration
      +@OpenAPIDefinition(info = @Info(title = "My App", description = "description"))
      +public class OpenAPIConfig {
      +}
      +
      +
      +
      +
      +

      How to Integrate Open API 3 with Spring project (not Spring Boot)?

      +
      +

      When your application is using spring without (spring-boot), you need to add beans and auto-configuration that are natively provided in spring-boot.

      +
      +
      +

      For example, lets assume you want load the swagger-ui in spring-mvc application:

      +
      +
      +
        +
      • +

        You mainly, need to add the springdoc-openapi module

        +
      • +
      +
      +
      +
      +
      <dependency>
      +   <groupId>org.springdoc</groupId>
      +   <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
      +   <version>last.version</version>
      +</dependency>
      +
      +
      +
      +
        +
      • +

        If you don’t have the spring-boot and spring-boot-autoconfigure dependencies, you need to add them. And pay attention to the compatibility matrix, between you spring.version and spring-boot.version. For example, in this case (spring.version=5.1.12.RELEASE):

        +
      • +
      +
      +
      +
      +
      		<dependency>
      +			<groupId>org.springframework.boot</groupId>
      +			<artifactId>spring-boot-autoconfigure</artifactId>
      +			<version>3.3.3</version>
      +		</dependency>
      +
      +
      +
      +
        +
      • +

        Scan for the springdoc-openapi 'auto-configuration classes that spring-boot automatically loads for you.

        +
      • +
      • +

        Depending on your module, you can find them on the file: spring.factories of each springdoc-openapi module.

        +
      • +
      +
      +
      +
      +
      @Configuration
      +@EnableWebMvc
      +public class WebConfig implements WebApplicationInitializer {
      +
      +	@Override
      +	public void onStartup(ServletContext servletContext)  {
      +		WebApplicationContext context = getContext();
      +		servletContext.addListener(new ContextLoaderListener(context));
      +		ServletRegistration.Dynamic dispatcher = servletContext.addServlet("RestServlet",
      +				new DispatcherServlet(context));
      +		dispatcher.setLoadOnStartup(1);
      +		dispatcher.addMapping("/*");
      +	}
      +
      +	private AnnotationConfigWebApplicationContext getContext() {
      +		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
      +		context.register(this.getClass(),
      +				SpringDocConfiguration.class,
      +				SpringDocConfigProperties.class,
      +				SpringDocSpecPropertiesConfiguration.class,
      +				SpringDocWebMvcConfiguration.class,
      +				MultipleOpenApiSupportConfiguration.class,
      +				SwaggerConfig.class,
      +				SwaggerUiConfigProperties.class,
      +				SwaggerUiOAuthProperties.class,
      +		);
      +		return context;
      +	}
      +}
      +
      +
      +
      +
      +
        +
      • +

        Depending on your module, you can find them on the file: org.springframework.boot.autoconfigure.AutoConfiguration.imports of each springdoc-openapi module.

        +
      • +
      • +

        For groups usage make sure your GroupedOpenApi Beans are scanned.

        +
      • +
      • +

        If additionally, you are using custom context path: /my-servlet-path. Make sure you declare the following property:

        +
      • +
      +
      +
      +
      +
      spring.mvc.servlet.path=/my-servlet-path
      +
      +
      +
      +
      +

      What is the compatibility matrix of springdoc-openapi with spring-boot ?

      +
      +

      springdoc-openapi 3.x is compatible with spring-boot 4.

      +
      +
      +

      In general, you should only pick the last stable version as per today 3.0.0-M1.

      +
      +
      +

      More precisely, this the exhaustive list of spring-boot versions against which springdoc-openapi has been built:

      +
      + ++++ + + + + + + + + + + +

      Spring Boot Versions

      Springdoc OpenAPI Versions

      4.0.x

      3.0.x

      +
      +
      +

      Why am i getting an error: Swagger UI unable to render definition, when overriding the default spring registered HttpMessageConverter?

      +
      +

      When overriding the default spring-boot registered HttpMessageConverter, you should have ByteArrayHttpMessageConverter registered as well to have proper springdoc-openapi support.

      +
      +
      +
      +
          converters.add(new ByteArrayHttpMessageConverter());
      +    converters.add(new MappingJackson2HttpMessageConverter(jacksonBuilder.build()));
      +
      +
      +
      +
      + + + + + +
      + + +Order is very important, when registering HttpMessageConverters. +
      +
      +
      +
      +

      Some parameters are not generated in the resulting OpenAPI spec.

      +
      +

      The issue is caused by the changes introduced by Spring-Boot 3.2.0 +in particular for the Parameter Name Discovery. +This can be fixed by adding the -parameters arg to the Maven Compiler Plugin.

      +
      +
      +
      +
      <plugin>
      +    <groupId>org.apache.maven.plugins</groupId>
      +    <artifactId>maven-compiler-plugin</artifactId>
      +    <configuration>
      +        <parameters>true</parameters>
      +    </configuration>
      +</plugin>
      +
      +
      +
      +
      +
      +
      + +
      +
      +
      + + \ No newline at end of file diff --git a/docs/v4/favicon.ico b/docs/v4/favicon.ico new file mode 100644 index 0000000..45468e6 Binary files /dev/null and b/docs/v4/favicon.ico differ diff --git a/docs/v4/features.html b/docs/v4/features.html new file mode 100644 index 0000000..b8192ce --- /dev/null +++ b/docs/v4/features.html @@ -0,0 +1,362 @@ + + + + + + + +Springdoc-openapi Features + + + + + + +
      +
      +
      + +
      +
      +

      Springdoc-openapi Features

      +
      +
      +

      Adding API Information and Security documentation

      +
      +

      The library uses spring-boot application auto-configured packages to scan for the following annotations in spring beans: OpenAPIDefinition and Info. +These annotations declare, API Information: Title, version, licence, security, servers, tags, security and externalDocs. +For better performance of documentation generation, declare @OpenAPIDefinition and @SecurityScheme annotations within a spring managed bean.

      +
      +
      +
      +

      Error Handling for REST using @ControllerAdvice

      +
      +

      To generate documentation automatically, make sure all the methods declare the HTTP Code responses using the annotation: @ResponseStatus

      +
      +
      +
      +

      Disabling the springdoc-openapi endpoints

      +
      +

      In order to disable the springdoc-openapi endpoint (/v3/api-docs by default) use the following property:

      +
      +
      +
      +
      # Disabling the /v3/api-docs endpoint
      +springdoc.api-docs.enabled=false
      +
      +
      +
      +
      +

      Disabling the swagger-ui

      +
      +

      In order to disable the swagger-ui, use the following property:

      +
      +
      +
      +
      # Disabling the swagger-ui
      +springdoc.swagger-ui.enabled=false
      +
      +
      +
      +
      +

      Swagger-ui configuration

      +
      +

      The library supports the swagger-ui official properties:

      +
      + +
      +

      You need to declare swagger-ui properties as spring-boot properties. +All these properties should be declared with the following prefix: springdoc.swagger-ui

      +
      +
      +
      +

      Selecting the Rest Controllers to include in the documentation

      +
      +

      Additionally, to @Hidden annotation from swagger-annotations, its possible to restrict the generated OpenAPI description using package or path configuration.

      +
      +
      +

      For the list of packages to include, use the following property:

      +
      +
      +
      +
      # Packages to include
      +springdoc.packagesToScan=com.package1, com.package2
      +
      +
      +
      +

      For the list of paths to include, use the following property:

      +
      +
      +
      +
      # Paths to include
      +springdoc.pathsToMatch=/v1, /api/balance/**
      +
      +
      +
      +
      +

      Spring-webflux/WebMvc.fn with Functional Endpoints

      +
      +

      Since version v1.5.0, a functional DSL has been introduced, thanks to this enhancement in the spring-framework: #25938

      +
      +
      +

      It’s an alternative functional API to the @RouterOperations annotations.

      +
      +
      +

      This is a sample DSL, to generate OpenAPI description to the webflux/WebMvc.fn REST endpoints:

      +
      +
      +
      +
      @Bean
      +RouterFunction<?> routes() {
      +    return route().GET("/foo", HANDLER_FUNCTION, ops -> ops
      +            .operationId("hello")
      +            .parameter(parameterBuilder().name("key1").description("My key1 description"))
      +            .parameter(parameterBuilder().name("key2").description("My key2 description"))
      +            .response(responseBuilder().responseCode("200").description("This is normal response description"))
      +            .response(responseBuilder().responseCode("404").description("This is another response description"))
      +    ).build();
      +}
      +
      +
      +
      +
      +

      Here is the link for some sample codes:

      +
      + +
      +

      And the Demo code, using the functional endpoints DSL:

      +
      + +
      +

      Since version v1.3.8, the support of functional endpoints has been added. +Two main annotations have been added for this purpose: @RouterOperations and @RouterOperation.

      +
      +
      +

      Only REST APIs with the @RouterOperations and @RouterOperation can be displayed on the swagger-ui.

      +
      +
      +
        +
      • +

        @RouterOperation: It can be used alone, if the Router bean contains one single route related to the REST API.. +When using @RouterOperation, its not mandatory to fill the path

        +
      • +
      • +

        @RouterOperation, can reference directly a spring Bean (beanClass property) and the underlying method (beanMethod property): Springdoc-openapi, will then inspect this method and the swagger annotations on this method level.

        +
      • +
      +
      +
      +
      +
      @Bean
      +@RouterOperation(beanClass = EmployeeService.class, beanMethod = "findAllEmployees")
      +RouterFunction<ServerResponse> getAllEmployeesRoute() {
      +   return route(GET("/employees").and(accept(MediaType.APPLICATION_JSON)),
      +         req -> ok().body(
      +               employeeService().findAllEmployees(), Employee.class));
      +}
      +
      +
      +
      +
      +
        +
      • +

        @RouterOperation, contains the @Operation annotation. +The @Operation annotation can also be placed on the bean method level if the property beanMethod is declared.

        +
      • +
      +
      +
      + + + + + +
      + + +Don’t forget to set operationId which is mandatory. +
      +
      +
      +
      +
      @Bean
      +@RouterOperation(operation = @Operation(operationId = "findEmployeeById", summary = "Find purchase order by ID", tags = { "MyEmployee" },
      +      parameters = { @Parameter(in = ParameterIn.PATH, name = "id", description = "Employee Id") },
      +      responses = { @ApiResponse(responseCode = "200", description = "successful operation", content = @Content(schema = @Schema(implementation = Employee.class))),
      +            @ApiResponse(responseCode = "400", description = "Invalid Employee ID supplied"),
      +            @ApiResponse(responseCode = "404", description = "Employee not found") }))
      +RouterFunction<ServerResponse> getEmployeeByIdRoute() {
      +   return route(GET("/employees/{id}"),
      +         req -> ok().body(
      +               employeeRepository().findEmployeeById(req.pathVariable("id")), Employee.class));
      +}
      +
      +
      +
      +
      +
        +
      • +

        @RouterOperations: This annotation should be used if the Router bean contains multiple routes. +When using RouterOperations, its mandatory to fill the path property.

        +
      • +
      • +

        A @RouterOperations, contains many @RouterOperation.

        +
      • +
      +
      +
      +
      +
      @RouterOperations({ @RouterOperation(path = "/getAllPersons", beanClass = PersonService.class, beanMethod = "getAll"),
      +      @RouterOperation(path = "/getPerson/{id}", beanClass = PersonService.class, beanMethod = "getById"),
      +      @RouterOperation(path = "/createPerson", beanClass = PersonService.class, beanMethod = "save"),
      +      @RouterOperation(path = "/deletePerson/{id}", beanClass = PersonService.class, beanMethod = "delete") })
      +@Bean
      +public RouterFunction<ServerResponse> personRoute(PersonHandler handler) {
      +   return RouterFunctions
      +         .route(GET("/getAllPersons").and(accept(MediaType.APPLICATION_JSON)), handler::findAll)
      +         .andRoute(GET("/getPerson/{id}").and(accept(MediaType.APPLICATION_STREAM_JSON)), handler::findById)
      +         .andRoute(POST("/createPerson").and(accept(MediaType.APPLICATION_JSON)), handler::save)
      +         .andRoute(DELETE("/deletePerson/{id}").and(accept(MediaType.APPLICATION_JSON)), handler::delete);
      +}
      +
      +
      +
      +
      +

      All the documentations filled using @RouterOperation, might be completed by the router function data. +For that, @RouterOperation fields must help identify uniquely the concerned route. +springdoc-openpi scans for a unique route related to a @RouterOperation annotation, using on the following criteria:

      +
      +
      +
        +
      • +

        by path

        +
      • +
      • +

        by path and RequestMethod

        +
      • +
      • +

        by path and produces

        +
      • +
      • +

        by path and consumes

        +
      • +
      • +

        by path and RequestMethod and produces

        +
      • +
      • +

        by path and RequestMethod and consumes

        +
      • +
      • +

        by path and produces and consumes

        +
      • +
      • +

        by path and RequestMethod and produces and consumes

        +
      • +
      +
      +
      +

      Some code samples are available on GITHUB of demos:

      +
      + +
      +

      And some project tests: (from app69 to app75)

      +
      + +
      +
      +

      Integration with WildFly

      +
      +
        +
      • +

        For WildFly users, you need to add the following dependency to make the swagger-ui work:

        +
      • +
      +
      +
      +
      +
         <dependency>
      +     <groupId>org.webjars</groupId>
      +     <artifactId>webjars-locator-jboss-vfs</artifactId>
      +     <version>0.1.0</version>
      +   </dependency>
      +
      +
      + + + +
      +
      +
      +
      + +
      +
      +
      + + \ No newline at end of file diff --git a/docs/v4/fonts/FontAwesome.otf b/docs/v4/fonts/FontAwesome.otf new file mode 100644 index 0000000..401ec0f Binary files /dev/null and b/docs/v4/fonts/FontAwesome.otf differ diff --git a/docs/v4/fonts/fontawesome-webfont.eot b/docs/v4/fonts/fontawesome-webfont.eot new file mode 100644 index 0000000..e9f60ca Binary files /dev/null and b/docs/v4/fonts/fontawesome-webfont.eot differ diff --git a/docs/v4/fonts/fontawesome-webfont.svg b/docs/v4/fonts/fontawesome-webfont.svg new file mode 100644 index 0000000..855c845 --- /dev/null +++ b/docs/v4/fonts/fontawesome-webfont.svg @@ -0,0 +1,2671 @@ + + + + +Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 + By ,,, +Copyright Dave Gandy 2016. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/v4/fonts/fontawesome-webfont.ttf b/docs/v4/fonts/fontawesome-webfont.ttf new file mode 100644 index 0000000..35acda2 Binary files /dev/null and b/docs/v4/fonts/fontawesome-webfont.ttf differ diff --git a/docs/v4/fonts/fontawesome-webfont.woff b/docs/v4/fonts/fontawesome-webfont.woff new file mode 100644 index 0000000..400014a Binary files /dev/null and b/docs/v4/fonts/fontawesome-webfont.woff differ diff --git a/docs/v4/fonts/fontawesome-webfont.woff2 b/docs/v4/fonts/fontawesome-webfont.woff2 new file mode 100644 index 0000000..4d13fc6 Binary files /dev/null and b/docs/v4/fonts/fontawesome-webfont.woff2 differ diff --git a/docs/v4/getting-started.html b/docs/v4/getting-started.html new file mode 100644 index 0000000..ba6611a --- /dev/null +++ b/docs/v4/getting-started.html @@ -0,0 +1,117 @@ + + + + + + + +Getting Started + + + + + + +
      +
      +
      + +
      +
      +

      Getting Started

      +
      +
      +

      For the integration between spring-boot and swagger-ui, add the library to the list of your project dependencies (No additional configuration is needed)

      +
      +
      +
      +
         <dependency>
      +      <groupId>org.springdoc</groupId>
      +      <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
      +      <version>3.0.0-M1</version>
      +   </dependency>
      +
      +
      +
      +

      This will automatically deploy swagger-ui to a spring-boot application:

      +
      +
      +
        +
      • +

        Documentation will be available in HTML format, using the official swagger-ui jars

        +
      • +
      • +

        The Swagger UI page will then be available at http://server:port/context-path/swagger-ui.html and the OpenAPI description will be available at the following url for json format: http://server:port/context-path/v3/api-docs

        +
        +
          +
        • +

          server: The server name or IP

          +
        • +
        • +

          port: The server port

          +
        • +
        • +

          context-path: The context path of the application

          +
        • +
        +
        +
      • +
      • +

        Documentation will be available in yaml format as well, on the following path : /v3/api-docs.yaml

        +
      • +
      +
      +
      + + + + + +
      + + +For custom path of the swagger documentation in HTML format, add a custom springdoc property, in your spring-boot configuration file: . +
      +
      +
      +
      +
      # swagger-ui custom path
      +springdoc.swagger-ui.path=/swagger-ui.html
      +
      +
      + + + +
      +
      +
      + +
      +
      +
      + + \ No newline at end of file diff --git a/docs/v4/img/LVM_Versicherung_2010_logo.svg.png b/docs/v4/img/LVM_Versicherung_2010_logo.svg.png new file mode 100644 index 0000000..5aac7e9 Binary files /dev/null and b/docs/v4/img/LVM_Versicherung_2010_logo.svg.png differ diff --git a/docs/v4/img/banner-logo.svg b/docs/v4/img/banner-logo.svg new file mode 100644 index 0000000..aeb97b5 --- /dev/null +++ b/docs/v4/img/banner-logo.svg @@ -0,0 +1,85 @@ + + + + + +Created with Fabric.js 4.6.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OpenAPI 3&Spring Boot + + \ No newline at end of file diff --git a/docs/v4/img/common.jpg b/docs/v4/img/common.jpg new file mode 100644 index 0000000..22a2138 Binary files /dev/null and b/docs/v4/img/common.jpg differ diff --git a/docs/v4/img/common.png b/docs/v4/img/common.png new file mode 100644 index 0000000..0fc4efe Binary files /dev/null and b/docs/v4/img/common.png differ diff --git a/docs/v4/img/contrastsecurity.svg b/docs/v4/img/contrastsecurity.svg new file mode 100644 index 0000000..21cd538 --- /dev/null +++ b/docs/v4/img/contrastsecurity.svg @@ -0,0 +1,17 @@ + + + Contrast_Logo_RGB + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/v4/img/dmTECH_Logo.jpg b/docs/v4/img/dmTECH_Logo.jpg new file mode 100644 index 0000000..470b6fb Binary files /dev/null and b/docs/v4/img/dmTECH_Logo.jpg differ diff --git a/docs/v4/img/doc-background-dark.svg b/docs/v4/img/doc-background-dark.svg new file mode 100644 index 0000000..3e7b63c --- /dev/null +++ b/docs/v4/img/doc-background-dark.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/docs/v4/img/doc-background.svg b/docs/v4/img/doc-background.svg new file mode 100644 index 0000000..301ff34 --- /dev/null +++ b/docs/v4/img/doc-background.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/docs/v4/img/gdnext.png b/docs/v4/img/gdnext.png new file mode 100644 index 0000000..1523834 Binary files /dev/null and b/docs/v4/img/gdnext.png differ diff --git a/docs/v4/img/github-logo.png b/docs/v4/img/github-logo.png new file mode 100644 index 0000000..8b25551 Binary files /dev/null and b/docs/v4/img/github-logo.png differ diff --git a/docs/v4/img/mercedes-benz.png b/docs/v4/img/mercedes-benz.png new file mode 100644 index 0000000..38a46ef Binary files /dev/null and b/docs/v4/img/mercedes-benz.png differ diff --git a/docs/v4/img/octicons-16.svg b/docs/v4/img/octicons-16.svg new file mode 100644 index 0000000..9e8fe28 --- /dev/null +++ b/docs/v4/img/octicons-16.svg @@ -0,0 +1,109 @@ + + Octicons (24px subset) + Octicons v12.1.0 by GitHub - https://primer.style/octicons/ - License: MIT + + + + @primer/octicons + 12.1.0 + A scalable set of icons handcrafted with <3 by GitHub + image/svg+xml + + + GitHub + + + + + Copyright (c) 2020 GitHub Inc. + + + + https://primer.style/octicons/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/v4/img/pets.png b/docs/v4/img/pets.png new file mode 100644 index 0000000..f14c9fe Binary files /dev/null and b/docs/v4/img/pets.png differ diff --git a/docs/v4/img/spring-io-24.png b/docs/v4/img/spring-io-24.png new file mode 100644 index 0000000..4aca7cf Binary files /dev/null and b/docs/v4/img/spring-io-24.png differ diff --git a/docs/v4/img/springdoc-openapi-conf.gif b/docs/v4/img/springdoc-openapi-conf.gif new file mode 100644 index 0000000..2dd4118 Binary files /dev/null and b/docs/v4/img/springdoc-openapi-conf.gif differ diff --git a/docs/v4/img/springdoc-openapi-prez.gif b/docs/v4/img/springdoc-openapi-prez.gif new file mode 100644 index 0000000..8b4ff47 Binary files /dev/null and b/docs/v4/img/springdoc-openapi-prez.gif differ diff --git a/docs/v4/img/springdoc-openapi.png b/docs/v4/img/springdoc-openapi.png new file mode 100644 index 0000000..a244f90 Binary files /dev/null and b/docs/v4/img/springdoc-openapi.png differ diff --git a/docs/v4/img/springdoc/springdoc-favicon.svg b/docs/v4/img/springdoc/springdoc-favicon.svg new file mode 100644 index 0000000..21eeef6 --- /dev/null +++ b/docs/v4/img/springdoc/springdoc-favicon.svg @@ -0,0 +1,166 @@ + + + + Created with Fabric.js 4.6.0 diff --git a/docs/v4/img/springdoc/springdoc-logo.svg b/docs/v4/img/springdoc/springdoc-logo.svg new file mode 100644 index 0000000..f3f7bb8 --- /dev/null +++ b/docs/v4/img/springdoc/springdoc-logo.svg @@ -0,0 +1,139 @@ + + + + Created with Fabric.js 4.6.0 diff --git a/docs/v4/img/static_content_transformation.png b/docs/v4/img/static_content_transformation.png new file mode 100644 index 0000000..edcc70d Binary files /dev/null and b/docs/v4/img/static_content_transformation.png differ diff --git a/docs/v4/index.html b/docs/v4/index.html new file mode 100644 index 0000000..e0fbc7f --- /dev/null +++ b/docs/v4/index.html @@ -0,0 +1,4452 @@ + + + + + + + +springdoc-openapi v3.0.0-M1 + + + + + + + + + + + +
      +
      +
      + +
      +
      +
      +
      +

      springdoc-openapi is on Open Collective. If you ❤️ this project consider becoming a sponsor.

      +
      +
      +

      This project is sponsored by

      +
      +

      + + +    + + + + + + + + + + + + +

      + +
      +
      +
      +

      1. Introduction

      +
      +
      +

      springdoc-openapi java library helps to automate the generation of API documentation using spring boot projects. +springdoc-openapi works by examining an application at runtime to infer API semantics based on spring configurations, class structure and various annotations.

      +
      +
      +

      Automatically generates documentation in JSON/YAML and HTML format APIs. +This documentation can be completed by comments using swagger-api annotations.

      +
      +
      +

      This library supports:

      +
      +
      +
        +
      • +

        OpenAPI 3

        +
      • +
      • +

        Spring-boot v4 (Java 17 & Jakarta EE 9)

        +
      • +
      • +

        JSR-303, specifically for @NotNull, @Min, @Max, and @Size.

        +
      • +
      • +

        Swagger-ui

        +
      • +
      • +

        OAuth 2

        +
      • +
      • +

        GraalVM native images

        +
      • +
      +
      +
      +

      The following video introduces the Library:

      +
      +
      +
      +spring.io conference +
      +
      +
      +

      This is a community-based project, not maintained by the Spring Framework Contributors (Pivotal).

      +
      +
      +
      +
      +

      2. Getting Started

      +
      +
      +

      For the integration between spring-boot and swagger-ui, add the library to the list of your project dependencies (No additional configuration is needed)

      +
      +
      +
      +
         <dependency>
      +      <groupId>org.springdoc</groupId>
      +      <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
      +      <version>3.0.0-M1</version>
      +   </dependency>
      +
      +
      +
      +

      This will automatically deploy swagger-ui to a spring-boot application:

      +
      +
      +
        +
      • +

        Documentation will be available in HTML format, using the official swagger-ui jars

        +
      • +
      • +

        The Swagger UI page will then be available at http://server:port/context-path/swagger-ui.html and the OpenAPI description will be available at the following url for json format: http://server:port/context-path/v3/api-docs

        +
        +
          +
        • +

          server: The server name or IP

          +
        • +
        • +

          port: The server port

          +
        • +
        • +

          context-path: The context path of the application

          +
        • +
        +
        +
      • +
      • +

        Documentation will be available in yaml format as well, on the following path : /v3/api-docs.yaml

        +
      • +
      +
      +
      + + + + + +
      + + +For custom path of the swagger documentation in HTML format, add a custom springdoc property, in your spring-boot configuration file: . +
      +
      +
      +
      +
      # swagger-ui custom path
      +springdoc.swagger-ui.path=/swagger-ui.html
      +
      +
      + + + +
      +
      +
      +

      3. Springdoc-openapi Modules

      +
      +
      +

      3.1. General overview

      +
      +
      +Architecture +
      +
      +
      +
      +

      3.2. Spring WebMvc support

      +
      +
        +
      • +

        Documentation will be available at the following url for json format: http://server:port/context-path/v3/api-docs

        +
        +
          +
        • +

          server: The server name or IP

          +
        • +
        • +

          port: The server port

          +
        • +
        • +

          context-path: The context path of the application

          +
        • +
        +
        +
      • +
      • +

        Documentation will be available in yaml format as well, on the following path : /v3/api-docs.yaml

        +
      • +
      • +

        Add the library to the list of your project dependencies. (No additional configuration is needed)

        +
      • +
      +
      +
      +
      +
         <dependency>
      +      <groupId>org.springdoc</groupId>
      +      <artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
      +      <version>3.0.0-M1</version>
      +   </dependency>
      +
      +
      +
      + + + + + +
      + + +This dependency is relevant if you want to generate the OpenAPI description without using the swagger-ui. +
      +
      +
      + + + + + +
      + + +For custom path of the OpenAPI documentation in Json format, add a custom springdoc property, in your spring-boot configuration file: +
      +
      +
      +
      +
      # /api-docs endpoint custom path
      +springdoc.api-docs.path=/api-docs
      +
      +
      +
      +
      +

      3.3. Spring WebFlux support

      +
      +
        +
      • +

        Documentation will be available in yaml format as well, on the following path : /v3/api-docs.yaml

        +
      • +
      • +

        Add the library to the list of your project dependencies (No additional configuration is needed)

        +
      • +
      +
      +
      +
      +
         <dependency>
      +      <groupId>org.springdoc</groupId>
      +      <artifactId>springdoc-openapi-starter-webflux-api</artifactId>
      +      <version>3.0.0-M1</version>
      +   </dependency>
      +
      +
      +
      +
      +

      3.4. Spring Hateoas support

      +
      +

      The support for Spring Hateoas is available using the dependency springdoc-openapi-hateoas.

      +
      +
      +

      The projects that use spring-boot-starter-hateoas should use:

      +
      +
      +
        +
      • +

        springdoc-openapi-starter-webmvc-api if they need only the access to the OpenAPI endpoints

        +
      • +
      • +

        OR springdoc-openapi-starter-webmvc-ui, if they need also the access to the swagger-ui

        +
      • +
      +
      +
      +
      +

      3.5. Spring Data Rest support

      +
      +

      springdoc-openapi project supports spring-boot-starter-data-rest types like: @RepositoryRestResource and QuerydslPredicate annotations.

      +
      +
      +

      The projects that use spring-boot-starter-data-rest should use:

      +
      +
      +
        +
      • +

        springdoc-openapi-starter-webmvc-api if they need only the access to the OpenAPI endpoints

        +
      • +
      • +

        OR springdoc-openapi-starter-webmvc-ui, if they need also the access to the swagger-ui

        +
      • +
      +
      +
      +
      +

      3.6. Spring Security support

      +
      +

      springdoc-openapi helps ignoring @AuthenticationPrincipal type in case it is used on REST Controllers.

      +
      +
      +

      springdoc-openapi supports also exposing Oauth2 endpoints of spring-security-oauth2-authorization-server.

      +
      +
      +

      The projects that use spring-boot-starter-security or spring-security-oauth2-authorization-server should use:

      +
      +
      +
        +
      • +

        springdoc-openapi-starter-webmvc-api if they depend on spring-boot-starter-web and they only need the access to the OpenAPI endpoints.

        +
      • +
      • +

        OR springdoc-openapi-starter-webmvc-ui, if they depend on spring-boot-starter-web and they also need the access to the swagger-ui.

        +
      • +
      • +

        OR springdoc-openapi-starter-webflux-api if they depend on spring-boot-starter-webflux and they only the access to the OpenAPI endpoints.

        +
      • +
      • +

        OR springdoc-openapi-starter-webflux-ui, if they depend on spring-boot-starter-webflux and they also need the access to the swagger-ui.

        +
      • +
      +
      +
      +
      +

      3.7. Actuator support

      +
      +
        +
      • +

        In order to display spring-boot-actuator endpoints, simply add the following property:

        +
      • +
      +
      +
      +
      +
      springdoc.show-actuator=true
      +
      +
      +
      +

      Starting from the release 1.5.1, it will be possible to expose the swagger-ui and the openapi endpoints on actuator port.

      +
      +
      + + + + + +
      + + +The actuator management port has to be different from the application port. +
      +
      +
      +

      To expose the swagger-ui, on the management port, you should set

      +
      +
      +
      +
      springdoc.use-management-port=true
      +# This property enables the openapi and swagger-ui endpoints to be exposed beneath the actuator base path.
      +management.endpoints.web.exposure.include=openapi, swagger-ui
      +
      +
      +
      +

      Once enabled, you should also be able to see the springdoc-openapi endpoints under: (host and port depends on your settings) +- http://serverName:managementPort/actuator

      +
      +
      +

      For example, if you have the following settings:

      +
      +
      +

      Two endpoints will be available:

      +
      +
      +
        +
      1. +

        REST API that holdes the OpenAPI definition:

        +
        +
          +
        • +

          http://serverName:managementPort/actuator/openapi

          +
        • +
        +
        +
      2. +
      3. +

        An Endpoint, that routes to the swagger-ui:

        +
        +
          +
        • +

          http://serverName:managementPort/actuator/swagger-ui

          +
        • +
        +
        +
      4. +
      +
      +
      +
      +
      management.server.port=9090
      +
      +
      +
      +

      For the example, you should also be able to see the springdoc-openapi endpoints:

      +
      +
      +
        +
      • +

        http://serverName:9090/actuator

        +
      • +
      • +

        http://serverName:9090/actuator/swagger-ui

        +
      • +
      • +

        http://serverName:9090/actuator/openapi

        +
      • +
      +
      +
      +

      All the path springdoc-openapi properties are not applicable when springdoc.use-management-port=true.

      +
      +
      + + + + + +
      + + +If you want to reach the application endpoints, from the swagger-ui deployed beneath the actuator base path, using a different port from your application, CORS for your endpoints on your application level should be enabled. +
      +
      +
      +

      Additionally, it is also possible to combine this property, with the existing property to display the actuator endpoints in the swagger-ui.

      +
      +
      +
      +
      springdoc.show-actuator=true
      +
      +
      +
      +

      Once enabled: +- A dedicated group for the actuator endpoints will be by default added. +- If no group is defined for the application, a default one will be added.

      +
      +
      +

      The swagger-ui will be then accessible through the actuator port:

      +
      +
      +
        +
      • +

        http://serverName:managementPort/actuator/swagger-ui

        +
      • +
      +
      +
      +

      If the management port is different from the application port and springdoc.use-management-port is not defined but springdoc.show-actuator is set to true:

      +
      +
      +
        +
      • +

        The swagger-ui will be then accessible through the application port. For example: http://serverName:applicationPort/swagger-ui.html

        +
      • +
      • +

        A dedicated group for the actuator endpoints will be by default added.

        +
      • +
      • +

        If no group is defined for the application, a default one will be added.

        +
      • +
      +
      +
      + + + + + +
      + + +If you want to reach the actuator endpoints for this case (different port from your application), CORS for your actuator endpoints should be enabled. +
      +
      +
      +

      Note: The naming of these new endpoints beneath the actuator base path cannot be customized for now.

      +
      +
      +
      +

      3.8. Spring Cloud Function Web support

      +
      +

      spring-cloud-function-web exposes Java Function as REST endpoint automatically. +* Since version v1.6.3, the support of functional endpoints has been added.

      +
      +
      +
        +
      • +

        These starters will display the OpenAPI description of the spring-cloud-function-web endpoints.

        +
        +
          +
        • +

          If you are using spring-web, simply add the springdoc-openapi-starter-webmvc-ui dependency.

          +
        • +
        • +

          If you are using spring-webflux, simply add the springdoc-openapi-starter-webflux-ui dependency.

          +
        • +
        +
        +
      • +
      +
      +
      +

      The customisation of the output can be achieved programmatically through OpenApiCustomizer or with the annotations: @RouterOperations and @RouterOperation. +For annotation usage, you have: +* @RouterOperation: It can be used alone, if the customisation is related to a single REST API. +When using @RouterOperation, it’s not mandatory to fill the path

      +
      +
      +
        +
      • +

        @RouterOperation, contains the @Operation annotation. +The @Operation annotation can also be placed on the bean method level if the property beanMethod is declared.

        +
      • +
      +
      +
      + + + + + +
      + + +Don’t forget to set operationId which is mandatory. +
      +
      +
      +
      +
      @Bean
      +@RouterOperation(operation = @Operation(description = "Say hello", operationId = "hello", tags = "persons",
      +        responses = @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = PersonDTO.class)))))
      +public Supplier<PersonDTO> helloSupplier() {
      +    return () -> new PersonDTO();
      +}
      +
      +
      +
      +
      +
        +
      • +

        @RouterOperations: This annotation should be used to describe the multiple REST APIs exposed by spring-cloud-function-web. +When using RouterOperations, it’s mandatory to fill the method property.

        +
      • +
      • +

        A @RouterOperations, contains many @RouterOperation.

        +
      • +
      +
      +
      +
      +
      @Bean
      +@RouterOperations({
      +        @RouterOperation(method = RequestMethod.GET, operation = @Operation(description = "Say hello GET", operationId = "lowercaseGET", tags = "persons")),
      +        @RouterOperation(method = RequestMethod.POST, operation = @Operation(description = "Say hello POST", operationId = "lowercasePOST", tags = "positions"))
      +})
      +public Function<Flux<String>, Flux<String>> lowercase() {
      +    return flux -> flux.map(value -> value.toLowerCase());
      +}
      +
      +
      +
      +
      +

      Some code samples are available on GITHUB of demos:

      +
      + +
      +
      +

      3.9. Kotlin support

      +
      +

      springdoc-openapi supports Kotlin types.

      +
      +
      +

      The projects that use Kotlin should use:

      +
      +
      +
        +
      • +

        springdoc-openapi-starter-webmvc-api if they depend on spring-boot-starter-web and they only need the access to the OpenAPI endpoints.

        +
      • +
      • +

        OR springdoc-openapi-starter-webmvc-ui, if they depend on spring-boot-starter-web and they also need the access to the swagger-ui.

        +
      • +
      • +

        OR springdoc-openapi-starter-webflux-api if they depend on spring-boot-starter-webflux and they only the access to the OpenAPI endpoints.

        +
      • +
      • +

        OR springdoc-openapi-starter-webflux-ui, if they depend on spring-boot-starter-webflux and they also need the access to the swagger-ui.

        +
      • +
      +
      +
      + + + + + +
      + + +In addition, your project should add jackson-module-kotlin as well to have the full support of Kotlin types: +
      +
      +
      +
      +
          <dependency>
      +        <groupId>com.fasterxml.jackson.module</groupId>
      +        <artifactId>jackson-module-kotlin</artifactId>
      +    </dependency>
      +
      +
      +
      +
      +

      3.10. Groovy support

      +
      +

      The projects that use Groovy should use:

      +
      +
      +
        +
      • +

        springdoc-openapi-starter-webmvc-api if they depend on spring-boot-starter-web and they only need the access to the OpenAPI endpoints.

        +
      • +
      • +

        OR springdoc-openapi-starter-webmvc-ui, if they depend on spring-boot-starter-web and they also need the access to the swagger-ui.

        +
      • +
      • +

        OR springdoc-openapi-starter-webflux-api if they depend on spring-boot-starter-webflux and they only the access to the OpenAPI endpoints.

        +
      • +
      • +

        OR springdoc-openapi-starter-webflux-ui, if they depend on spring-boot-starter-webflux and they also need the access to the swagger-ui.

        +
      • +
      +
      +
      +
      +

      3.11. Javadoc support

      +
      +

      springdoc-openapi can introspect Javadoc annotations and comments:

      +
      +
      +
        +
      • +

        The javadoc comment of a method: is resolved as the @Operation description

        +
      • +
      • +

        @return : is resolved as the @Operation response description

        +
      • +
      • +

        The javadoc comment of an attribute: is resolved as '@Schema' description for this field.

        +
      • +
      +
      +
      +

      The projects that needs Javadoc support should use:

      +
      +
      +
        +
      • +

        springdoc-openapi-starter-webmvc-api if they depend on spring-boot-starter-web and they only need the access to the OpenAPI endpoints.

        +
      • +
      • +

        OR springdoc-openapi-starter-webmvc-ui, if they depend on spring-boot-starter-web and they also need the access to the swagger-ui.

        +
      • +
      • +

        OR springdoc-openapi-starter-webflux-api if they depend on spring-boot-starter-webflux and they only the access to the OpenAPI endpoints.

        +
      • +
      • +

        OR springdoc-openapi-starter-webflux-ui, if they depend on spring-boot-starter-webflux and they also need the access to the swagger-ui.

        +
      • +
      +
      +
      + + + + + +
      + + +In addition, your project should add therapi-runtime-javadoc to read Javadoc comments at runtime. +Ensure that you add it as well as its annotation processor to your project’s dependencies. Otherwise, the Javadoc support will fail silently. +
      +
      +
      +
      +
          <!--Annotation processor -->
      +    <build>
      +        <plugins>
      +            <plugin>
      +                <groupId>org.apache.maven.plugins</groupId>
      +                <artifactId>maven-compiler-plugin</artifactId>
      +                <configuration>
      +                    <annotationProcessorPaths>
      +                        <path>
      +                            <groupId>com.github.therapi</groupId>
      +                            <artifactId>therapi-runtime-javadoc-scribe</artifactId>
      +                            <version>0.15.0</version>
      +                        </path>
      +                    </annotationProcessorPaths>
      +                </configuration>
      +            </plugin>
      +        </plugins>
      +    </build>
      +
      +    <!-- Runtime library -->
      +    <dependency>
      +        <groupId>com.github.therapi</groupId>
      +        <artifactId>therapi-runtime-javadoc</artifactId>
      +        <version>0.15.0</version>
      +    </dependency>
      +
      +
      +
      + + + + + +
      + + +If both a swagger-annotation description and a javadoc comment are present. The value of the swagger-annotation description will be used. +
      +
      +
      +
      +

      3.12. Springdoc-openapi BOM

      +
      +

      Starting from version v2.8.7, springdoc-openapi provides a BOM (Bill of Materials) to manage the dependencies of the project. +You can declare it in your project as follows:

      +
      +
      +
      +
          <dependencyManagement>
      +        <dependencies>
      +            <dependency>
      +                <groupId>org.springdoc</groupId>
      +                <artifactId>springdoc-openapi-bom</artifactId>
      +                <version>3.0.0-M1</version>
      +                <type>pom</type>
      +                <scope>import</scope>
      +            </dependency>
      +        </dependencies>
      +    </dependencyManagement>
      +
      +
      +
      +
      +
      +
      +

      4. Springdoc-openapi Features

      +
      +
      +

      4.1. Adding API Information and Security documentation

      +
      +

      The library uses spring-boot application auto-configured packages to scan for the following annotations in spring beans: OpenAPIDefinition and Info. +These annotations declare, API Information: Title, version, licence, security, servers, tags, security and externalDocs. +For better performance of documentation generation, declare @OpenAPIDefinition and @SecurityScheme annotations within a spring managed bean.

      +
      +
      +
      +

      4.2. Error Handling for REST using @ControllerAdvice

      +
      +

      To generate documentation automatically, make sure all the methods declare the HTTP Code responses using the annotation: @ResponseStatus

      +
      +
      +
      +

      4.3. Disabling the springdoc-openapi endpoints

      +
      +

      In order to disable the springdoc-openapi endpoint (/v3/api-docs by default) use the following property:

      +
      +
      +
      +
      # Disabling the /v3/api-docs endpoint
      +springdoc.api-docs.enabled=false
      +
      +
      +
      +
      +

      4.4. Disabling the swagger-ui

      +
      +

      In order to disable the swagger-ui, use the following property:

      +
      +
      +
      +
      # Disabling the swagger-ui
      +springdoc.swagger-ui.enabled=false
      +
      +
      +
      +
      +

      4.5. Swagger-ui configuration

      +
      +

      The library supports the swagger-ui official properties:

      +
      + +
      +

      You need to declare swagger-ui properties as spring-boot properties. +All these properties should be declared with the following prefix: springdoc.swagger-ui

      +
      +
      +
      +

      4.6. Selecting the Rest Controllers to include in the documentation

      +
      +

      Additionally, to @Hidden annotation from swagger-annotations, its possible to restrict the generated OpenAPI description using package or path configuration.

      +
      +
      +

      For the list of packages to include, use the following property:

      +
      +
      +
      +
      # Packages to include
      +springdoc.packagesToScan=com.package1, com.package2
      +
      +
      +
      +

      For the list of paths to include, use the following property:

      +
      +
      +
      +
      # Paths to include
      +springdoc.pathsToMatch=/v1, /api/balance/**
      +
      +
      +
      +
      +

      4.7. Spring-webflux/WebMvc.fn with Functional Endpoints

      +
      +

      Since version v1.5.0, a functional DSL has been introduced, thanks to this enhancement in the spring-framework: #25938

      +
      +
      +

      It’s an alternative functional API to the @RouterOperations annotations.

      +
      +
      +

      This is a sample DSL, to generate OpenAPI description to the webflux/WebMvc.fn REST endpoints:

      +
      +
      +
      +
      @Bean
      +RouterFunction<?> routes() {
      +    return route().GET("/foo", HANDLER_FUNCTION, ops -> ops
      +            .operationId("hello")
      +            .parameter(parameterBuilder().name("key1").description("My key1 description"))
      +            .parameter(parameterBuilder().name("key2").description("My key2 description"))
      +            .response(responseBuilder().responseCode("200").description("This is normal response description"))
      +            .response(responseBuilder().responseCode("404").description("This is another response description"))
      +    ).build();
      +}
      +
      +
      +
      +
      +

      Here is the link for some sample codes:

      +
      + +
      +

      And the Demo code, using the functional endpoints DSL:

      +
      + +
      +

      Since version v1.3.8, the support of functional endpoints has been added. +Two main annotations have been added for this purpose: @RouterOperations and @RouterOperation.

      +
      +
      +

      Only REST APIs with the @RouterOperations and @RouterOperation can be displayed on the swagger-ui.

      +
      +
      +
        +
      • +

        @RouterOperation: It can be used alone, if the Router bean contains one single route related to the REST API.. +When using @RouterOperation, its not mandatory to fill the path

        +
      • +
      • +

        @RouterOperation, can reference directly a spring Bean (beanClass property) and the underlying method (beanMethod property): Springdoc-openapi, will then inspect this method and the swagger annotations on this method level.

        +
      • +
      +
      +
      +
      +
      @Bean
      +@RouterOperation(beanClass = EmployeeService.class, beanMethod = "findAllEmployees")
      +RouterFunction<ServerResponse> getAllEmployeesRoute() {
      +   return route(GET("/employees").and(accept(MediaType.APPLICATION_JSON)),
      +         req -> ok().body(
      +               employeeService().findAllEmployees(), Employee.class));
      +}
      +
      +
      +
      +
      +
        +
      • +

        @RouterOperation, contains the @Operation annotation. +The @Operation annotation can also be placed on the bean method level if the property beanMethod is declared.

        +
      • +
      +
      +
      + + + + + +
      + + +Don’t forget to set operationId which is mandatory. +
      +
      +
      +
      +
      @Bean
      +@RouterOperation(operation = @Operation(operationId = "findEmployeeById", summary = "Find purchase order by ID", tags = { "MyEmployee" },
      +      parameters = { @Parameter(in = ParameterIn.PATH, name = "id", description = "Employee Id") },
      +      responses = { @ApiResponse(responseCode = "200", description = "successful operation", content = @Content(schema = @Schema(implementation = Employee.class))),
      +            @ApiResponse(responseCode = "400", description = "Invalid Employee ID supplied"),
      +            @ApiResponse(responseCode = "404", description = "Employee not found") }))
      +RouterFunction<ServerResponse> getEmployeeByIdRoute() {
      +   return route(GET("/employees/{id}"),
      +         req -> ok().body(
      +               employeeRepository().findEmployeeById(req.pathVariable("id")), Employee.class));
      +}
      +
      +
      +
      +
      +
        +
      • +

        @RouterOperations: This annotation should be used if the Router bean contains multiple routes. +When using RouterOperations, its mandatory to fill the path property.

        +
      • +
      • +

        A @RouterOperations, contains many @RouterOperation.

        +
      • +
      +
      +
      +
      +
      @RouterOperations({ @RouterOperation(path = "/getAllPersons", beanClass = PersonService.class, beanMethod = "getAll"),
      +      @RouterOperation(path = "/getPerson/{id}", beanClass = PersonService.class, beanMethod = "getById"),
      +      @RouterOperation(path = "/createPerson", beanClass = PersonService.class, beanMethod = "save"),
      +      @RouterOperation(path = "/deletePerson/{id}", beanClass = PersonService.class, beanMethod = "delete") })
      +@Bean
      +public RouterFunction<ServerResponse> personRoute(PersonHandler handler) {
      +   return RouterFunctions
      +         .route(GET("/getAllPersons").and(accept(MediaType.APPLICATION_JSON)), handler::findAll)
      +         .andRoute(GET("/getPerson/{id}").and(accept(MediaType.APPLICATION_STREAM_JSON)), handler::findById)
      +         .andRoute(POST("/createPerson").and(accept(MediaType.APPLICATION_JSON)), handler::save)
      +         .andRoute(DELETE("/deletePerson/{id}").and(accept(MediaType.APPLICATION_JSON)), handler::delete);
      +}
      +
      +
      +
      +
      +

      All the documentations filled using @RouterOperation, might be completed by the router function data. +For that, @RouterOperation fields must help identify uniquely the concerned route. +springdoc-openpi scans for a unique route related to a @RouterOperation annotation, using on the following criteria:

      +
      +
      +
        +
      • +

        by path

        +
      • +
      • +

        by path and RequestMethod

        +
      • +
      • +

        by path and produces

        +
      • +
      • +

        by path and consumes

        +
      • +
      • +

        by path and RequestMethod and produces

        +
      • +
      • +

        by path and RequestMethod and consumes

        +
      • +
      • +

        by path and produces and consumes

        +
      • +
      • +

        by path and RequestMethod and produces and consumes

        +
      • +
      +
      +
      +

      Some code samples are available on GITHUB of demos:

      +
      + +
      +

      And some project tests: (from app69 to app75)

      +
      + +
      +
      +

      4.8. Integration with WildFly

      +
      +
        +
      • +

        For WildFly users, you need to add the following dependency to make the swagger-ui work:

        +
      • +
      +
      +
      +
      +
         <dependency>
      +     <groupId>org.webjars</groupId>
      +     <artifactId>webjars-locator-jboss-vfs</artifactId>
      +     <version>0.1.0</version>
      +   </dependency>
      +
      +
      + + + +
      +
      +
      +
      +

      5. Springdoc-openapi Properties

      +
      +
      +

      springdoc-openapi relies on standard spring configuration properties (yml or properties) using the standard files locations.

      +
      +
      +

      5.1. springdoc-openapi core properties

      + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Parameter nameDefault ValueDescription

      springdoc.api-docs.path

      /v3/api-docs

      String, For custom path of the OpenAPI documentation in Json format.

      springdoc.api-docs.enabled

      true

      Boolean. To disable the springdoc-openapi endpoint (/v3/api-docs by default).

      springdoc.packages-to-scan

      *

      List of Strings. The list of packages to scan (comma separated)

      springdoc.paths-to-match

      /*

      List of Strings. The list of paths to match (comma separated)

      springdoc.produces-to-match

      /*

      List of Strings. The list of produces mediaTypes to match (comma separated)

      springdoc.headers-to-match

      /*

      List of Strings. The list of headers to match (comma separated)

      springdoc.consumes-to-match

      /*

      List of Strings. The list of consumes mediaTypes to match (comma separated)

      springdoc.paths-to-exclude

      List of Strings. The list of paths to exclude (comma separated)

      springdoc.packages-to-exclude

      List of Strings. The list of packages to exclude (comma separated)

      springdoc.default-consumes-media-type

      application/json

      String. The default consumes media type.

      springdoc.default-produces-media-type

      /

      String. The default produces media type.

      springdoc.cache.disabled

      false

      Boolean. To disable the springdoc-openapi cache of the calculated OpenAPI.

      springdoc.show-actuator

      false

      Boolean. To display the actuator endpoints.

      springdoc.auto-tag-classes

      true

      Boolean. To disable the springdoc-openapi automatic tags.

      springdoc.model-and-view-allowed

      false

      Boolean. To allow RestControllers with ModelAndView return to appear in the OpenAPI description.

      springdoc.override-with-generic-response

      true

      Boolean. When true, automatically adds @ControllerAdvice responses to all the generated responses.

      springdoc.group-configs[0].group

      String. The group name

      springdoc.group-configs[0].display-name

      String. The display name of the group.

      springdoc.group-configs[0].packages-to-scan

      *

      List of Strings. The list of packages to scan for a group (comma separated)

      springdoc.group-configs[0].paths-to-match

      /*

      List of Strings. The list of paths to match for a group (comma separated)

      springdoc.group-configs[0].paths-to-exclude

      ``

      List of Strings. The list of paths to exclude for a group (comma separated)

      springdoc.group-configs[0].packages-to-exclude

      List of Strings. The list of packages to exclude for a group (comma separated)

      springdoc.group-configs[0].produces-to-match

      /*

      List of Strings. The list of produces mediaTypes to match (comma separated)

      springdoc.group-configs[0].consumes-to-match

      /*

      List of Strings. The list of consumes mediaTypes to match (comma separated)

      springdoc.group-configs[0].headers-to-match

      /*

      List of Strings. The list of headers to match (comma separated)

      springdoc.webjars.prefix

      /webjars

      String. To change the webjars prefix that is visible the URL of swagger-ui for spring-webflux.

      springdoc.api-docs.resolve-schema-properties

      false

      Boolean. To enable property resolver on @Schema (name, title and description).

      springdoc.remove-broken-reference-definitions

      true

      Boolean. To disable removal of broken reference definitions.

      springdoc.writer-with-default-pretty-printer

      false

      Boolean. To enable pretty print of the OpenApi specification.

      springdoc.model-converters.deprecating-converter.enabled

      true

      Boolean. To disable deprecating model converter.

      springdoc.model-converters.polymorphic-converter.enabled

      true

      Boolean. To disable polymorphic model converter.

      springdoc.model-converters.pageable-converter.enabled

      true

      Boolean. To disable pageable model converter.

      springdoc.model-converters.sort-converter.enabled

      true

      Boolean. To disable Sort converter.

      springdoc.use-fqn

      false

      Boolean. To enable fully qualified names.

      springdoc.show-login-endpoint

      false

      Boolean. To make spring security login-endpoint visible.

      springdoc.pre-loading-locales

      List of Strings. The list of locales to load OpenAPI on application startup (comma separated). If not specified, it will preload with the default Locale.

      springdoc.writer-with-order-by-keys

      false

      Boolean. Enable a deterministic/alphabetical ordering.

      springdoc.use-management-port

      false

      Boolean. To expose the swagger-ui on the actuator management port.

      springdoc.disable-i18n

      false

      Boolean. To disable automatic translation using i18n.

      springdoc.show-spring-cloud-functions

      true

      Boolean. To display the spring-cloud-function web endpoints.

      springdoc.enable-groovy

      true

      Boolean. To enable Groovy support.

      springdoc.enable-spring-security

      true

      Boolean. To enable spring-security support.

      springdoc.enable-kotlin

      true

      Boolean. To enable Kotlin support.

      springdoc.enable-hateoas

      true

      Boolean. To enable spring-hateoas support.

      springdoc.enable-data-rest

      true

      Boolean. To enable spring-data-rest support.

      springdoc.api-docs.version

      openapi_3_1

      String. To choose OpenAPI 3.0 or OpenAPI 3.1 (using the value OPENAPI_3_1).

      springdoc.default-flat-param-object

      false

      Boolean. To default flatten parameter.

      springdoc.default-support-form-data

      false

      Boolean. To default set parameters to form data when specifying api to accept form data.

      springdoc.nullable-request-parameter-enabled

      true

      Boolean. To default Enable Support for nullable request parameters in Kotlin.

      springdoc.show-oauth2-endpoints

      false

      Boolean. To make spring security oauth2-endpoint visible.

      springdoc.api-docs.resolve-extensions-properties

      false

      Boolean. To enable support of spring property resolver for @ExtensionProperty.

      springdoc.enable-default-api-docs

      true

      Boolean. To enable default OpenAPI endpoint /v3/api-docs.

      springdoc.trim-kotlin-indent

      false

      Boolean. Adjust indentation when parsing the @Operation annotation in Kotlin.

      springdoc.allowed-locales

      List of Strings. The list of allowed locales for OpenAPI (comma separated, for example US,fr-CA).

      springdoc.enable-extra-schemas

      true

      Boolean. To enable default support for extra Schemas, from java.time package like LocalTime, Duration, but also other Java classes like java.util.Locale or java.nio.charset.Charset

      springdoc.explicit-object-schema

      false

      Boolean. Set explicit-object-schema to true to always include type: object in the schema, or to false to omit type: object.

      springdoc.use-arbitrary-schemas

      false

      Boolean. When set to true, schemas without a defined type will be deserialized as an ArbitrarySchema (with no type), instead of an ObjectSchema with type: object.

      +
      +
      +

      5.2. swagger-ui properties

      +
      +
        +
      • +

        The support of the swagger-ui properties is available on springdoc-openapi. See Official documentation.

        +
      • +
      • +

        You can use the same swagger-ui properties in the documentation as Spring Boot properties.

        +
      • +
      +
      +
      + + + + + +
      + + +All these properties should be declared with the following prefix: springdoc.swagger-ui +
      +
      + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Parameter nameDefault ValueDescription

      springdoc.swagger-ui.path

      /swagger-ui.html

      String, For custom path of the swagger-ui HTML documentation.

      springdoc.swagger-ui.enabled

      true

      Boolean. To disable the swagger-ui endpoint (/swagger-ui.html by default).

      springdoc.swagger-ui.configUrl

      /v3/api-docs/swagger-config

      String. URL to fetch external configuration document from.

      springdoc.swagger-ui.layout

      BaseLayout

      String. The name of a component available via the plugin system to use as the top-level layout for Swagger UI.

      springdoc.swagger-ui.validatorUrl

      By default, Swagger UI does not validate specs. You can use this parameter to set a validator URL, for example for against swagger.io’s online validator.

      springdoc.swagger-ui.tryItOutEnabled

      false

      Boolean. Controls whether the "Try it out" section should be enabled by default.

      springdoc.swagger-ui.filter

      false

      Boolean OR String. If set, enables filtering. The top bar will show an edit box that you can use to filter the tagged operations that are shown. Can be Boolean to enable or disable, or a string, in which case filtering will be enabled using that string as the filter expression. Filtering is case sensitive matching the filter expression anywhere inside the tag.

      springdoc.swagger-ui.operationsSorter

      Function=(a ⇒ a). Apply a sort to the operation list of each API. It can be 'alpha' (sort by paths alphanumerically), 'method' (sort by HTTP method) or a function (see Array.prototype.sort() to know how sort function works). Default is the order returned by the server unchanged.

      springdoc.swagger-ui.tagsSorter

      Function=(a ⇒ a). Apply a sort to the tag list of each API. It can be 'alpha' (sort by paths alphanumerically) or a function see Array.prototype.sort() to learn how to write a sort function). Two tag name strings are passed to the sorter for each pass. Default is the order determined by Swagger UI.

      springdoc.swagger-ui.oauth2RedirectUrl

      /swagger-ui/oauth2-redirect.html

      String. OAuth redirect URL.

      springdoc.swagger-ui.displayOperationId

      false

      Boolean. Controls the display of operationId in operations list. The default is false.

      springdoc.swagger-ui.displayRequestDuration

      false

      Boolean. Controls the display of the request duration (in milliseconds) for "Try it out" requests.

      springdoc.swagger-ui.deepLinking

      false

      Boolean. If set to true, enables deep linking for tags and operations. See the [Deep Linking documentation](swagger.io/docs/open-source-tools/swagger-ui/usage/deep-linking) for more information.

      springdoc.swagger-ui.defaultModelsExpandDepth

      1

      Number. The default expansion depth for models (set to -1 completely hide the models).

      springdoc.swagger-ui.defaultModelExpandDepth

      1

      Number. The default expansion depth for the model on the model-example section.

      springdoc.swagger-ui.defaultModelRendering

      String=["example"*, "model"]. Controls how the model is shown when the API is first rendered. (The user can always switch the rendering for a given model by clicking the 'Model' and 'Example Value' links.)

      springdoc.swagger-ui.docExpansion

      String=["list"*, "full", "none"]. Controls the default expansion setting for the operations and tags. It can be 'list' (expands only the tags), 'full' (expands the tags and operations) or 'none' (expands nothing).

      springdoc.swagger-ui.maxDisplayedTags

      Number. If set, limits the number of tagged operations displayed to at most this many. The default is to show all operations.

      springdoc.swagger-ui.showExtensions

      false

      Boolean. Controls the display of vendor extension (x-) fields and values for Operations, Parameters, and Schema.

      springdoc.swagger-ui.url

      String.To configure, the path of a custom OpenAPI file . Will be ignored if urls is used.

      springdoc.swagger-ui.showCommonExtensions

      false

      Boolean. Controls the display of extensions (pattern, maxLength, minLength, maximum, minimum) fields and values for Parameters.

      springdoc.swagger-ui.supportedSubmitMethods

      Array=[get, put, post, delete, options, head, patch, trace]. List of HTTP methods that have the "Try it out" feature enabled. An empty array disables "Try it out" for all operations. This does not filter the operations from the display.

      springdoc.swagger-ui.queryConfigEnabled

      false

      Boolean. Disabled since v1.6.0. This parameter enables (legacy) overriding configuration parameters via URL search params. See security advisory before enabling this feature.

      springdoc.swagger-ui.oauth. additionalQueryStringParams

      String. Additional query parameters added to authorizationUrl and tokenUrl.

      springdoc.swagger-ui.disable-swagger-default-url

      false

      Boolean. To disable the swagger-ui default petstore url. (Available since v1.4.1).

      springdoc.swagger-ui.urls[0].url

      URL. The url of the swagger group, used by Topbar plugin. URLs must be unique among all items in this array, since they’re used as identifiers.

      springdoc.swagger-ui.urls[0].name

      String. The name of the swagger group, used by Topbar plugin. Names must be unique among all items in this array, since they’re used as identifiers.

      springdoc.swagger-ui.urlsPrimaryName

      String. The name of the swagger group which will be displayed when Swagger UI loads.

      springdoc.swagger-ui.oauth.clientId

      String. Default clientId. MUST be a string.

      springdoc.swagger-ui.oauth.clientSecret

      String. Default clientSecret. Never use this parameter in your production environment. It exposes crucial security information. This feature is intended for dev/test environments only.

      springdoc.swagger-ui.oauth.realm

      String. realm query parameter (for OAuth 1) added to authorizationUrl and tokenUrl.

      springdoc.swagger-ui.oauth.appName

      String. OAuth application name, displayed in authorization popup.

      springdoc.swagger-ui.oauth.scopeSeparator

      String. OAuth scope separator for passing scopes, encoded before calling, default value is a space (encoded value %20).

      springdoc.swagger-ui.csrf.enabled

      false

      Boolean. To enable CSRF support

      springdoc.swagger-ui.csrf.use-local-storage

      false

      Boolean. To get the CSRF token from the Local Storage.

      springdoc.swagger-ui.csrf.use-session-storage

      false

      Boolean. To get the CSRF token from the Session Storage.

      springdoc.swagger-ui.csrf.cookie-name

      XSRF-TOKEN

      String. Optional CSRF, to set the CSRF cookie name.

      springdoc.swagger-ui.csrf.header-name

      X-XSRF-TOKEN

      String. Optional CSRF, to set the CSRF header name.

      springdoc.swagger-ui.syntaxHighlight.activated

      true

      Boolean. Whether syntax highlighting should be activated or not.

      springdoc.swagger-ui.syntaxHighlight.theme

      agate

      String. String=["agate"*, "arta", "monokai", "nord", "obsidian", "tomorrow-night"]. Highlight.js syntax coloring theme to use. (Only these 6 styles are available.)

      springdoc.swagger-ui.oauth. useBasicAuthentication WithAccessCodeGrant

      false

      Boolean. Only activated for the accessCode flow. During the authorization_code request to the tokenUrl, pass the Client Password using the HTTP Basic Authentication scheme (Authorization header with Basic base64encode(client_id + client_secret)).

      springdoc.swagger-ui.oauth. usePkceWithAuthorization CodeGrant

      false

      Boolean.Only applies to authorizatonCode flows. Proof Key for Code Exchange brings enhanced security for OAuth public clients.

      springdoc.swagger-ui.persistAuthorization

      false

      Boolean. If set to true, it persists authorization data and it would not be lost on browser close/refresh

      springdoc.swagger-ui.use-root-path

      false

      Boolean. If set to true, the swagger-ui will be accessible from the application root path directly.

      + + + +
      +
      +
      +
      +

      6. Springdoc-openapi Plugins

      +
      +
      +

      6.1. Maven plugin

      +
      +

      The aim of springdoc-openapi-maven-plugin is to generate json and yaml OpenAPI description during build time. +The plugin works during integration-tests phase, and generate the OpenAPI description. +The plugin works in conjunction with spring-boot-maven plugin.

      +
      +
      +

      You can test it during the integration tests phase using the maven command:

      +
      +
      +
      +
      mvn verify
      +
      +
      +
      +

      In order to use this functionality, you need to add the plugin declaration on the plugins section of your pom.xml:

      +
      +
      +
      +
      <plugin>
      +    <groupId>org.springframework.boot</groupId>
      +    <artifactId>spring-boot-maven-plugin</artifactId>
      +    <version>${spring-boot-maven-plugin.version}</version>
      +    <configuration>
      +        <jvmArguments>-Dspring.application.admin.enabled=true</jvmArguments>
      +    </configuration>
      +    <executions>
      +        <execution>
      +            <goals>
      +                <goal>start</goal>
      +                <goal>stop</goal>
      +            </goals>
      +        </execution>
      +    </executions>
      +</plugin>
      +<plugin>
      +    <groupId>org.springdoc</groupId>
      +    <artifactId>springdoc-openapi-maven-plugin</artifactId>
      +    <version>1.5</version>
      +    <executions>
      +        <execution>
      +            <id>integration-test</id>
      +            <goals>
      +                <goal>generate</goal>
      +            </goals>
      +        </execution>
      +    </executions>
      +</plugin>
      +
      +
      +
      +

      For more custom settings of the springdoc-openapi-maven-plugin, you can consult the plugin documentation:

      +
      + +
      +
      +

      6.2. Gradle plugin

      +
      +

      This plugin allows you to generate an OpenAPI 3 specification for a Spring Boot application from a Gradle build.

      +
      +
      +
      +
      plugins {
      +      id("org.springframework.boot") version "3.1.2"
      +      id("org.springdoc.openapi-gradle-plugin") version "1.9.0"
      +}
      +
      +
      +
      +
      +

      When you add this plugin and its runtime dependency plugins to your build file, the plugin creates the following tasks:

      +
      +
      +
        +
      • +

        forkedSpringBootRun

        +
      • +
      • +

        generateOpenApiDocs

        +
      • +
      +
      +
      +
      +
      gradle clean generateOpenApiDocs
      +
      +
      +
      +

      For more custom configuration of springdoc-openapi-gradle-plugin ,you can consult the plugin documentation:

      +
      + +
      +
      +
      + +
      +

      8. Migrating from SpringFox

      +
      +
      +
        +
      • +

        Remove springfox and swagger 2 dependencies. Add springdoc-openapi-starter-webmvc-ui dependency instead.

        +
      • +
      +
      +
      +
      +
         <dependency>
      +      <groupId>org.springdoc</groupId>
      +      <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
      +      <version>3.0.0-M1</version>
      +   </dependency>
      +
      +
      +
      +
        +
      • +

        Replace swagger 2 annotations with swagger 3 annotations (it is already included with springdoc-openapi-starter-webmvc-ui dependency). +Package for swagger 3 annotations is io.swagger.v3.oas.annotations.

        +
        +
          +
        • +

          @Api@Tag

          +
        • +
        • +

          @ApiIgnore@Parameter(hidden = true) or @Operation(hidden = true) or @Hidden

          +
        • +
        • +

          @ApiImplicitParam@Parameter

          +
        • +
        • +

          @ApiImplicitParams@Parameters

          +
        • +
        • +

          @ApiModel@Schema

          +
        • +
        • +

          @ApiModelProperty(allowEmptyValue = true)@Schema(nullable = true)

          +
        • +
        • +

          @ApiModelProperty@Schema

          +
        • +
        • +

          @ApiOperation(value = "foo", notes = "bar")@Operation(summary = "foo", description = "bar")

          +
        • +
        • +

          @ApiParam@Parameter

          +
        • +
        • +

          @ApiResponse(code = 404, message = "foo")@ApiResponse(responseCode = "404", description = "foo")

          +
        • +
        +
        +
      • +
      • +

        This step is optional: Only if you have multiple Docket beans replace them with GroupedOpenApi beans.

        +
      • +
      +
      +
      +

      Before:

      +
      +
      +
      +
        @Bean
      +  public Docket publicApi() {
      +      return new Docket(DocumentationType.SWAGGER_2)
      +              .select()
      +              .apis(RequestHandlerSelectors.basePackage("org.github.springshop.web.public"))
      +              .paths(PathSelectors.regex("/public.*"))
      +              .build()
      +              .groupName("springshop-public")
      +              .apiInfo(apiInfo());
      +  }
      +
      +  @Bean
      +  public Docket adminApi() {
      +      return new Docket(DocumentationType.SWAGGER_2)
      +              .select()
      +              .apis(RequestHandlerSelectors.basePackage("org.github.springshop.web.admin"))
      +              .paths(PathSelectors.regex("/admin.*"))
      +              .apis(RequestHandlerSelectors.withMethodAnnotation(Admin.class))
      +              .build()
      +              .groupName("springshop-admin")
      +              .apiInfo(apiInfo());
      +  }
      +
      +
      +
      +
      +

      Now:

      +
      +
      +
      +
        @Bean
      +  public GroupedOpenApi publicApi() {
      +      return GroupedOpenApi.builder()
      +              .group("springshop-public")
      +              .pathsToMatch("/public/**")
      +              .build();
      +  }
      +  @Bean
      +  public GroupedOpenApi adminApi() {
      +      return GroupedOpenApi.builder()
      +              .group("springshop-admin")
      +              .pathsToMatch("/admin/**")
      +              .addOpenApiMethodFilter(method -> method.isAnnotationPresent(Admin.class))
      +              .build();
      +  }
      +
      +
      +
      +
      +

      If you have only one Docket — remove it and instead add properties to your application.properties:

      +
      +
      +
      +
      springdoc.packagesToScan=package1, package2
      +springdoc.pathsToMatch=/v1, /api/balance/**
      +
      +
      +
      +
        +
      • +

        Add bean of OpenAPI type. See example:

        +
      • +
      +
      +
      +
      +
        @Bean
      +  public OpenAPI springShopOpenAPI() {
      +      return new OpenAPI()
      +              .info(new Info().title("SpringShop API")
      +              .description("Spring shop sample application")
      +              .version("v0.0.1")
      +              .license(new License().name("Apache 2.0").url("http://springdoc.org")))
      +              .externalDocs(new ExternalDocumentation()
      +              .description("SpringShop Wiki Documentation")
      +              .url("https://springshop.wiki.github.org/docs"));
      +  }
      +
      +
      +
      +
      + +
      +
      +
      +
      +

      9. Other resources

      +
      + +
      +

      9.2. Dependencies repository

      +
      +

      The springdoc-openapi libraries are hosted on maven central repository. +The artifacts can be viewed accessed at the following locations:

      +
      +
      +

      Releases:

      +
      + +
      +

      Snapshots:

      +
      + +
      +
      +
      +
      + +
      +
      +

      springdoc-openapi is on Open Collective.

      +
      +
      +

      If you ❤️ this project consider becoming a sponsor.

      +
      +
      +

      This money is used to cover project expenses and your donation will help the project live and grow successfully.

      +
      +
      +

      Thank you to our bronze sponsors!

      +
      +

      + + +    + + + + + + + + + + + + +

      +
      +

      10.1. Benefits of being a bronze sponsor

      +
      +

      Bronze sponsors donate $50 per month to the project, and get the following benefits:

      +
      +
      +
        +
      • +

        You will receive a Sponsor badge 🎖!. Visibility on the front page of springdoc.org in the welcome page (about 55,000 views/month on May, 2022).

        +
      • +
      • +

        “Thank you” tweet from `springdoc team'.

        +
      • +
      +
      +
      +
      +

      10.2. Benefits of being a silver sponsor

      +
      +

      Silver sponsors donate $100 per month to the project, and get the following benefits:

      +
      +
      +
        +
      • +

        Same benefits as bronze sponsors (visibility on main pages, and thank you tweet).

        +
      • +
      • +

        The ability to get support for 2 issues every month, non transferable.

        +
      • +
      • +

        If issues are not created by the end of the month, it is lost

        +
      • +
      +
      +
      +
      +

      10.3. Benefits of being a gold sponsor

      +
      +

      Gold sponsors donate $500 per month to the project, and get the following benefits:

      +
      +
      +
        +
      • +

        Same benefits as silver sponsors (visibility on main pages, and thank you tweet).

        +
      • +
      • +

        The ability to get support for 10 issues every month, non transferable.

        +
      • +
      • +

        Company logos on all springdoc.org page footers

        +
      • +
      • +

        If issues are not created by the end of the month, the remaining ones are lost.

        +
      • +
      +
      +
      +
      +
      +
      +

      11. Special Thanks

      +
      +
      +
        +
      • +

        Thank you to The Spring Team for sharing all relevant resources around Spring projects.

        +
      • +
      • +

        Thanks a lot JetBrains for supporting springdoc-openapi project.

        +
      • +
      +
      +
      +
      +JetBrains logo +
      +
      +
      +
      +
      +

      12. F.A.Q

      +
      +
      +

      12.1. How can I define multiple OpenAPI definitions in one Spring Boot project?

      +
      +

      You can define your own groups of API based on the combination of: API paths and packages to scan. Each group should have a unique groupName. +The OpenAPI description of this group, will be available by default on:

      +
      +
      +
        +
      • +

        http://server:port/context-path/v3/api-docs/groupName

        +
      • +
      +
      +
      +

      To enable the support of multiple OpenAPI definitions, a bean of type GroupedOpenApi needs to be defined.

      +
      +
      +

      For the following Group definition(based on package path), the OpenAPI description URL will be : /v3/api-docs/stores

      +
      +
      +
      +
      @Bean
      +public GroupedOpenApi storeOpenApi() {
      +   String paths[] = {"/store/**"};
      +   return GroupedOpenApi.builder().group("stores").pathsToMatch(paths)
      +         .build();
      +}
      +
      +
      +
      +
      +

      For the following Group definition (based on package name), the OpenAPI description URL will be: /v3/api-docs/users

      +
      +
      +
      +
      @Bean
      +public GroupedOpenApi userOpenApi() {
      +   String packagesToscan[] = {"test.org.springdoc.api.app68.api.user"};
      +   return GroupedOpenApi.builder().group("users").packagesToScan(packagesToscan)
      +         .build();
      +}
      +
      +
      +
      +
      +

      For the following Group definition(based on path), the OpenAPI description URL will be: /v3/api-docs/pets

      +
      +
      +
      +
      @Bean
      +public GroupedOpenApi petOpenApi() {
      +   String paths[] = {"/pet/**"};
      +   return GroupedOpenApi.builder().group("pets").pathsToMatch(paths)
      +         .build();
      +}
      +
      +
      +
      +
      +

      For the following Group definition (based on package name and path), the OpenAPI description URL will be: /v3/api-docs/groups

      +
      +
      +
      +
      @Bean
      +public GroupedOpenApi groupOpenApi() {
      +   String paths[] = {"/v1/**"};
      +   String packagesToscan[] = {"test.org.springdoc.api.app68.api.user", "test.org.springdoc.api.app68.api.store"};
      +   return GroupedOpenApi.builder().group("groups").pathsToMatch(paths).packagesToScan(packagesToscan)
      +         .build();
      +}
      +
      +
      +
      +
      +

      For more details about the usage, you can have a look at the following sample Test:

      +
      + +
      +
      +

      12.2. How can I configure Swagger UI?

      +
      +
        +
      • +

        The support of the swagger official properties is available on springdoc-openapi. See Official documentation.

        +
      • +
      • +

        You can use the same swagger properties in the documentation as Spring Boot properties.

        +
      • +
      +
      +
      + + + + + +
      + + +All these properties should be declared with the following prefix: springdoc.swagger-ui +
      +
      +
      +
      +

      12.3. How can I filter the resources documented in the output specification by the provided group?

      +
      +
        +
      • +

        You can use the standard swagger-ui property filter.

        +
      • +
      +
      +
      +
      +
      springdoc.swagger-ui.filter=group-a
      +
      +
      +
      +
      +

      12.4. How can I disable/enable Swagger UI generation based on env variable?

      +
      +
        +
      • +

        This property helps you disable only the UI.

        +
      • +
      +
      +
      +
      +
      springdoc.swagger-ui.enabled=false
      +
      +
      +
      +
      +

      12.5. How can I control the default expansion setting for the operations and tags, in the Swagger UI ,

      +
      +
        +
      • +

        You can set this property in your application.yml like so for example:

        +
      • +
      +
      +
      +
      +
      springdoc.swagger-ui.doc-expansion= none
      +
      +
      +
      +
      +

      12.6. How can I change the layout of the swagger-ui?

      +
      +
        +
      • +

        For layout options, you can use swagger-ui configuration options. For example:

        +
      • +
      +
      +
      +
      +
      springdoc.swagger-ui.layout=BaseLayout
      +
      +
      +
      +
      +

      12.7. How can I sort endpoints alphabetically?

      +
      +
        +
      • +

        You can use the following springdoc-openapi properties:

        +
      • +
      +
      +
      +
      +
      #For sorting endpoints alphabetically
      +springdoc.swagger-ui.operationsSorter=alpha
      +#For sorting tags alphabetically
      +springdoc.swagger-ui.tagsSorter=alpha
      +
      +
      +
      +
      +

      12.8. How can I disable the try it out button?

      +
      +
        +
      • +

        You have to set the following property:

        +
      • +
      +
      +
      +
      +
      springdoc.swagger-ui.supportedSubmitMethods=get, put, post, delete, options, head, patch, trace
      +
      +
      +
      +
      +

      12.9. How can I add Reusable Enums ?

      +
      +
        +
      • +

        You should add @Schema(enumAsRef = true) on your enum.

        +
      • +
      +
      +
      +
      +

      12.10. How can i apply enumAsRef = true to all enums ?

      +
      +
        +
      • +

        Declare the following property:

        +
      • +
      +
      +
      +
      +
      static {
      +    io.swagger.v3.core.jackson.ModelResolver.enumsAsRef = true;
      +}
      +
      +
      +
      +
      +

      12.11. How can I explicitly set which paths to filter?

      +
      +
        +
      • +

        You can set list of paths to include using the following property:

        +
      • +
      +
      +
      +
      +
      springdoc.pathsToMatch=/v1, /api/balance/**
      +
      +
      +
      +
      +

      12.12. How can I explicitly set which packages to scan?

      +
      +
        +
      • +

        You can set list of packages to include using the following property:

        +
      • +
      +
      +
      +
      +
      springdoc.packagesToScan=package1, package2
      +
      +
      +
      +
      +

      12.13. How can I set Swagger properties programmatically?

      +
      +

      These can be set by creating a swaggerUiConfig bean as follows:

      +
      +
      +
      +
      @Bean
      +@Primary
      +fun swaggerUiConfig(config: SwaggerUiConfigProperties): SwaggerUiConfigProperties {
      +    config.showCommonExtensions = true
      +    config.queryConfigEnabled = true
      +    return config
      +}
      +
      +
      +
      +
      +
      +

      12.14. How can I ignore some field of model ?

      +
      +
        +
      • +

        You can use the following annotation on the top of the field that you want to hide:

        +
      • +
      • +

        @Schema(hidden = true)

        +
      • +
      +
      +
      +
      +

      12.15. How can I ignore @AuthenticationPrincipal parameter from spring-security ?

      +
      +
        +
      • +

        A solution workaround would be to use: @Parameter(hidden = true)

        +
      • +
      • +

        The projects that use spring-boot-starter-security or spring-security-oauth2-authorization-server should use:

        +
        +
          +
        • +

          springdoc-openapi-starter-webmvc-api if they depend on spring-boot-starter-web and they only need the access to the OpenAPI endpoints.

          +
        • +
        • +

          OR springdoc-openapi-starter-webmvc-ui, if they depend on spring-boot-starter-web and they also need the access to the swagger-ui.

          +
        • +
        • +

          OR springdoc-openapi-starter-webflux-api if they depend on spring-boot-starter-webflux and they only the access to the OpenAPI endpoints.

          +
        • +
        • +

          OR springdoc-openapi-starter-webflux-ui, if they depend on spring-boot-starter-webflux and they also need the access to the swagger-ui.

          +
        • +
        +
        +
      • +
      +
      +
      +
      +

      12.16. Is there a Gradle plugin available?

      +
      +
        +
      • +

        Yes. More details are available, in the gradle plugin section.

        +
      • +
      +
      +
      +
      +

      12.17. How can I hide a parameter from the documentation ?

      +
      +
        +
      • +

        You can use @Parameter(hidden = true)

        +
      • +
      +
      +
      +
      +

      12.18. Is @Parameters annotation supported ?

      +
      +
        +
      • +

        Yes

        +
      • +
      +
      +
      +
      +

      12.19. Does springdoc-openapi support Jersey?

      +
      + +
      +
      +
      +

      12.20. Can springdoc-openapi generate API only for @RestController?

      +
      +
        +
      • +

        @RestController is equivalent to @Controller + @RequestMapping on the type level.

        +
      • +
      • +

        For some legacy apps, we are constrained to still support both.

        +
      • +
      • +

        If you need to hide the @Controller on the type level, in this case, you can use: @Hidden on controller level.

        +
      • +
      • +

        Please note this annotation can be also used to hide some methods from the generated documentation.

        +
      • +
      +
      +
      +
      +

      12.21. Are the following validation annotations supported : @NotEmpty @NotBlank @PositiveOrZero @NegativeOrZero?

      +
      +
        +
      • +

        Yes

        +
      • +
      +
      +
      +
      +

      12.22. How can I map Pageable (spring-data-commons) object to correct URL-Parameter in Swagger UI?

      +
      +

      The support for Pageable of spring-data-commons is available out-of-the box since springdoc-openapi v1.6.0. +For this, you have to combine @ParameterObject annotation with the Pageable type.

      +
      +
      +

      Before springdoc-openapi v1.6.0:

      +
      +
      +
        +
      • +

        You can use as well @ParameterObject instead of @PageableAsQueryParam for HTTP GET methods.

        +
      • +
      +
      +
      +
      +
      static {
      +    getConfig().replaceParameterObjectWithClass(org.springframework.data.domain.Pageable.class, Pageable.class)
      +            .replaceParameterObjectWithClass(org.springframework.data.domain.PageRequest.class, Pageable.class);
      +}
      +
      +
      +
      +
      +
        +
      • +

        Another solution, is to configure Pageable manually:

        +
        +
          +
        • +

          you will have to declare the explicit mapping of Pageable fields as Query Params and add the @Parameter(hidden = true) Pageable pageable on your pageable parameter.

          +
        • +
        • +

          You should also, declare the annotation @PageableAsQueryParam provided by springdoc-openapi on the method level, or declare your own if need to define your custom description, defaultValue, …​

          +
        • +
        +
        +
      • +
      +
      +
      +

      If you want to disable the support of spring Pageable Type, you can use:

      +
      +
      +
      +
      springdoc.model-converters.pageable-converter.enabled=false
      +
      +
      +
      + + + + + +
      + + +The property springdoc.model-converters.pageable-converter.enabled is only available since v1.5.11+ +
      +
      +
      +
      +

      12.23. How can I generate enums in the generated description?

      +
      +
        +
      • +

        You could add a property allowableValues, to @Parameter. For example:

        +
      • +
      +
      +
      +
      +
      @GetMapping("/example")
      +public Object example(@Parameter(name ="json", schema = @Schema(description = "var 1",type = "string", allowableValues = {"1", "2"}))
      +String json) {
      +   return null;
      +}
      +
      +
      +
      +
      +
        +
      • +

        or you could override toString on your enum:

        +
      • +
      +
      +
      +
      +
      @Override
      +@JsonValue
      +public String toString() {
      +   return String.valueOf(action);
      +}
      +
      +
      +
      +
      +
      +

      12.24. How can I deploy springdoc-openapi-starter-webmvc-ui behind a reverse proxy?

      +
      +
        +
      • +

        If your application is running behind a proxy, a load-balancer or in the cloud, the request information (like the host, port, scheme…​) might change along the way. Your application may be running on 10.10.10.10:8080, but HTTP clients should only see example.org.

        +
      • +
      • +

        RFC7239 "Forwarded Headers" defines the Forwarded HTTP header; proxies can use this header to provide information about the original request. You can configure your application to read those headers and automatically use that information when creating links and sending them to clients in HTTP 302 responses, JSON documents or HTML pages. There are also non-standard headers, like X-Forwarded-Host, X-Forwarded-Port, X-Forwarded-Proto, X-Forwarded-Ssl, and X-Forwarded-Prefix.

        +
      • +
      • +

        If the proxy adds the commonly used X-Forwarded-For and X-Forwarded-Proto headers, setting server.forward-headers-strategy to NATIVE is enough to support those. With this option, the Web servers themselves natively support this feature; you can check their specific documentation to learn about specific behavior.

        +
      • +
      • +

        You need to make sure the following header is set in your reverse proxy configuration: X-Forwarded-Prefix

        +
      • +
      • +

        For example, using Apache 2, configuration:

        +
      • +
      +
      +
      +
      +
      RequestHeader set X-Forwarded-Prefix "/custom-path"
      +
      +
      +
      +
        +
      • +

        Then, in your Spring Boot application make sure your application handles this header: X-Forwarded-For. There are two ways to achieve this:

        +
      • +
      +
      +
      +
      +
      server.use-forward-headers=true
      +
      +
      +
      +
        +
      • +

        If this is not enough, Spring Framework provides a ForwardedHeaderFilter. You can register it as a Servlet Filter in your application by setting server.forward-headers-strategy is set to FRAMEWORK.

        +
      • +
      • +

        Since Spring Boot 2.2, this is the new property to handle reverse proxy headers:

        +
      • +
      +
      +
      +
      +
      server.forward-headers-strategy=framework
      +
      +
      +
      +
        +
      • +

        And you can add the following bean to your application:

        +
      • +
      +
      +
      +
      +
      @Bean
      +ForwardedHeaderFilter forwardedHeaderFilter() {
      +   return new ForwardedHeaderFilter();
      +}
      +
      +
      +
      +
      +
        +
      • +

        If you need to manually adjust the URL displayed in the Swagger UI, implement the ServerBaseUrlCustomizer interface. This might be necessary to remove the port number, for example.

        +
      • +
      +
      +
      +
      +
      @Bean
      +public class CustomServerBaseUrlCustomizer implements ServerBaseUrlCustomizer {
      +    @Override
      +    public String customize(String serverBaseUrl) {
      +        try {
      +            URL url = new URL(serverBaseUrl);
      +            if (url.getHost().contains(".com")) {
      +                serverBaseUrl = new URL(url.getProtocol(),url.getHost(),url.getFile()).toString();
      +            }
      +        } catch (MalformedURLException ex) {
      +            // nothing we can do
      +        }
      +
      +        return serverBaseUrl;
      +    }
      +}
      +
      +
      +
      +
      +
      +

      12.25. Is @JsonView annotations in Spring MVC APIs supported?

      +
      +
        +
      • +

        Yes

        +
      • +
      +
      +
      +
      +

      12.26. Adding springdoc-openapi-starter-webmvc-ui dependency breaks my public/index.html welcome page

      +
      +
        +
      • +

        If you already have static content on your root, and you don’t want it to be overridden by springdoc-openapi-starter-webmvc-ui configuration, you can just define a custom configuration of the swagger-ui, in order not to override the configuration of your files from in your context-root:

        +
      • +
      • +

        For example use:

        +
      • +
      +
      +
      +
      +
      springdoc.swagger-ui.path= /swagger-ui/api-docs.html
      +
      +
      +
      +
      +

      12.27. How can I test the Swagger UI?

      + +
      +
      +

      12.28. How can I customise the OpenAPI object ?

      +
      + +
      +
      +
      +
      @Bean
      +public OpenApiCustomizer consumerTypeHeaderOpenAPICustomizer() {
      +return openApi -> openApi.getPaths().values().stream().flatMap(pathItem -> pathItem.readOperations().stream())
      +    .forEach(operation -> operation.addParametersItem(new HeaderParameter().$ref("#/components/parameters/myConsumerTypeHeader")));
      +}
      +
      +
      +
      +
      + + + + + +
      + + +This bean OpenApiCustomizer will be applied to the Default OpenAPI only. +
      +
      +
      +

      If you need the OpenApiCustomizer to applied to GroupedOpenApi as well, then use GlobalOpenApiCustomizer instead.

      +
      +
      +
      +

      12.29. How can I return an empty content as response?

      +
      +
        +
      • +

        It is be possible to handle as return an empty content as response using, one of the following syntaxes:

        +
      • +
      • +

        content = @Content

        +
      • +
      • +

        content = @Content(schema = @Schema(hidden = true))

        +
      • +
      • +

        For example:

        +
      • +
      +
      +
      +
      +
      @Operation(summary = "Get thing", responses = {
      +      @ApiResponse(description = "Successful Operation", responseCode = "200", content = @Content(mediaType = "application/json", schema = @Schema(implementation = String.class))),
      +      @ApiResponse(responseCode = "404", description = "Not found", content = @Content),
      +      @ApiResponse(responseCode = "401", description = "Authentication Failure", content = @Content(schema = @Schema(hidden = true))) })
      +@RequestMapping(path = "/testme", method = RequestMethod.GET)
      +ResponseEntity<String> testme() {
      +   return ResponseEntity.ok("Hello");
      +}
      +
      +
      +
      +
      +
      +

      12.30. How are endpoints with multiple consuming media types supported?

      +
      +
        +
      • +

        An overloaded method on the same class, with the same HTTP Method and path, will have as a result, only one OpenAPI Operation generated.

        +
      • +
      • +

        In addition, it’s recommended to have the @Operation in the level of one of the overloaded methods. Otherwise it might be overridden if it’s declared many times within the same overloaded method.

        +
      • +
      +
      +
      +
      +

      12.31. How can I get yaml and json (OpenAPI) in compile time?

      +
      + +
      +
      +
      +

      12.32. What are the ignored types in the documentation?

      +
      + +
      +
      +
      +

      12.33. How can i disable ignored types:

      +
      +

      If you don’t want to ignore the types Principal, Locale, HttpServletRequest, and others,:

      +
      +
      +
      +
      SpringDocUtils.getConfig().removeRequestWrapperToIgnore(HttpServletRequest.class)
      +
      +
      +
      +
      +
      +

      12.34. How do I add authorization header in requests?

      +
      +
        +
      • +

        You should add the @SecurityRequirement tags to your protected APIs.

        +
      • +
      • +

        For example:

        +
      • +
      +
      +
      +
      +
      @Operation(security = { @SecurityRequirement(name = "bearer-key") })
      +
      +
      +
      +
        +
      • +

        And the security definition sample:

        +
      • +
      +
      +
      +
      +
      @Bean
      + public OpenAPI customOpenAPI() {
      +   return new OpenAPI()
      +          .components(new Components()
      +          .addSecuritySchemes("bearer-key",
      +          new SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("bearer").bearerFormat("JWT")));
      +}
      +
      +
      +
      +
      +
      +

      12.35. Differentiation to Springfox project

      +
      +
        +
      • +

        OAS 3 was released in July 2017, and there was no release of springfox to support OAS 3. +springfox covers for the moment only swagger 2 integration with Spring Boot. The latest release date is June 2018. So, in terms of maintenance there is a big lack of support lately.

        +
      • +
      • +

        We decided to move forward and share the library that we already used on our internal projects, with the community.

        +
      • +
      • +

        The biggest difference with springfox, is that we integrate new features not covered by springfox:

        +
      • +
      • +

        The integration between Spring Boot and OpenAPI 3 standard.

        +
      • +
      • +

        We rely on on swagger-annotations and swagger-ui only official libraries.

        +
      • +
      • +

        We support new features on Spring 5, like spring-webflux with annotated and functional style.

        +
      • +
      • +

        We do our best to answer all the questions and address all issues or enhancement requests

        +
      • +
      +
      +
      +
      +

      12.36. How do I migrate to OpenAPI 3 with springdoc-openapi

      +
      +
        +
      • +

        There is no relation between springdoc-openapi and springfox.If you want to migrate to OpenAPI 3:

        +
      • +
      • +

        Remove all the dependencies and the related code to springfox

        +
      • +
      • +

        Add springdoc-openapi-starter-webmvc-ui dependency

        +
      • +
      • +

        If you don’t want to serve the UI from your root path or there is a conflict with an existing configuration, you can just change the following property:

        +
      • +
      +
      +
      +
      +
      springdoc.swagger-ui.path=/you-path/swagger-ui.html
      +
      +
      +
      +
      +

      12.37. How can I set a global header?

      +
      +
        +
      • +

        You may have global parameters with Standard OpenAPI description.

        +
      • +
      • +

        If you need the definitions to appear globally (within every group), no matter if the group fulfills the conditions specified on the GroupedOpenApi , you can use OpenAPI Bean.

        +
      • +
      • +

        You can define common parameters under parameters in the global components section and reference them elsewhere via $ref. You can also define global header parameters.

        +
      • +
      • +

        For this, you can override to OpenAPI Bean, and set the global headers or parameters definition on the components level.

        +
      • +
      +
      +
      +
      +
      @Bean
      +public OpenAPI customOpenAPI(@Value("${springdoc.version}") String appVersion) {
      + return new OpenAPI()
      +        .components(new Components().addSecuritySchemes("basicScheme", new SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("basic"))
      +        .addParameters("myHeader1", new Parameter().in("header").schema(new StringSchema()).name("myHeader1")).addHeaders("myHeader2", new Header().description("myHeader2 header").schema(new StringSchema())))
      +        .info(new Info()
      +        .title("Petstore API")
      +        .version(appVersion)
      +        .description("This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.")
      +        .termsOfService("http://swagger.io/terms/")
      +        .license(new License().name("Apache 2.0").url("http://springdoc.org")));
      +}
      +
      +
      +
      +
      +
      +

      12.38. Are Callbacks supported?

      +
      +
        +
      • +

        Yes

        +
      • +
      +
      +
      +
      +

      12.39. How can I define SecurityScheme ?

      +
      +
        +
      • +

        You can use: @SecurityScheme annotation.

        +
      • +
      • +

        Or you can define it programmatically, by overriding OpenAPI Bean:

        +
      • +
      +
      +
      +
      +
       @Bean
      + public OpenAPI customOpenAPI(@Value("${springdoc.version}") String appVersion) {
      +  return new OpenAPI()
      +   .components(new Components().addSecuritySchemes("basicScheme",
      +   new SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("basic")))
      +   info(new Info().title("SpringShop API").version(appVersion)
      +   .license(new License().name("Apache 2.0").url("http://springdoc.org")));
      + }
      +
      +
      +
      +
      +
      +

      12.40. How can I hide an operation or a controller from documentation ?

      +
      +
        +
      • +

        You can use @io.swagger.v3.oas.annotations.Hidden annotation at @RestController, @RestControllerAdvice and method level

        +
      • +
      • +

        The @Hidden annotation on exception handler methods, is considered when building generic (error) responses from @ControllerAdvice exception handlers.

        +
      • +
      • +

        Or use: @Operation(hidden = true)

        +
      • +
      +
      +
      +
      +

      12.41. How to configure global security schemes?

      +
      +
        +
      • +

        For global SecurityScheme, you can add it inside your own OpenAPI definition:

        +
      • +
      +
      +
      +
      +
      @Bean
      +public OpenAPI customOpenAPI() {
      +    return new OpenAPI().components(new Components()
      +    .addSecuritySchemes("basicScheme", new SecurityScheme()
      +    .type(SecurityScheme.Type.HTTP).scheme("basic"))).info(new Info().title("Custom API")
      +    .version("100")).addTagsItem(new Tag().name("mytag"));
      +}
      +
      +
      +
      +
      +
      +

      12.42. Can I use spring property with swagger annotations?

      +
      +
        +
      • +

        The support of spring property resolver for @Info: title * description * version * termsOfService

        +
      • +
      • +

        The support of spring property resolver for @Info.license: name * url

        +
      • +
      • +

        The support of spring property resolver for @Info.contact: name * email * url

        +
      • +
      • +

        The support of spring property resolver for @Operation: description * summary

        +
      • +
      • +

        The support of spring property resolver for @Parameter: description * name

        +
      • +
      • +

        The support of spring property resolver for @ApiResponse: description

        +
      • +
      • +

        Its also possible to declare security URLs for @OAuthFlow: openIdConnectUrl * authorizationUrl * refreshUrl * tokenUrl

        +
      • +
      • +

        The support of spring property resolver for @Schema: name * title * description , by setting springdoc.api-docs.resolve-schema-properties to true

        +
      • +
      • +

        The support of spring property resolver for @ExtensionProperty by setting springdoc.api-docs.resolve-extensions-properties to true

        +
      • +
      +
      +
      +
      +

      12.43. How is server URL generated ?

      +
      +
        +
      • +

        Generating automatically server URL may be useful, if the documentation is not present.

        +
      • +
      • +

        If the server annotations are present, they will be used instead.

        +
      • +
      +
      +
      +
      +

      12.44. How can I disable springdoc-openapi cache?

      +
      +
        +
      • +

        By default, the OpenAPI description is calculated once, and then cached.

        +
      • +
      • +

        Sometimes the same swagger-ui is served behind internal and external proxies. some users want the server URL, to be computed on each http request.

        +
      • +
      • +

        In order to disable springdoc cache, you will have to set the following property:

        +
      • +
      +
      +
      +
      +
      springdoc.cache.disabled= true
      +
      +
      +
      +
      +

      12.45. How can I expose the mvc api-docs endpoints without using the swagger-ui?

      +
      +
        +
      • +

        You should use the springdoc-openapi-core dependency only:

        +
      • +
      +
      +
      +
      +
      <dependency>
      +  <groupId>org.springdoc</groupId>
      +  <artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
      +  <version>latest.version</version>
      +</dependency>
      +
      +
      +
      +
      +

      12.46. How can I disable springdoc-openapi endpoints ?

      +
      +
        +
      • +

        Use the following property:

        +
      • +
      +
      +
      +
      +
      springdoc.api-docs.enabled=false
      +
      +
      +
      +
      +

      12.47. How can I hide Schema of the the response ?

      +
      +
        +
      • +

        To hide the response element, using @Schema annotation, as follows, at operation level:

        +
      • +
      +
      +
      +
      +
      @Operation(responses = @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(hidden = true))))
      +
      +
      +
      +
        +
      • +

        Or directly at @ApiResponses level:

        +
      • +
      +
      +
      +
      +
      @ApiResponses(value = {@ApiResponse(responseCode = "200", content = @Content(schema = @Schema(hidden = true))) })
      +OR
      +@ApiResponse(responseCode = "404", description = "Not found", content = @Content)
      +
      +
      +
      +
      +

      12.48. What is the URL of the swagger-ui, when I set a different context-path?

      +
      +
        +
      • +

        If you use different context-path:

        +
      • +
      +
      +
      +
      +
      server.servlet.context-path= /foo
      +
      +
      +
      +
        +
      • +

        The swagger-ui will be available on the following URL:

        +
        +
          +
        • +

          http://server:port/foo/swagger-ui.html

          +
        • +
        +
        +
      • +
      +
      +
      +
      +

      12.49. Can I customize OpenAPI object programmatically?

      +
      +
        +
      • +

        You can Define your own OpenAPI Bean: If you need the definitions to appear globally (within every group), no matter if the group fulfills the conditions specified on the GroupedOpenApi , you can use OpenAPI Bean.

        +
      • +
      +
      +
      +
      +
      @Bean
      +public OpenAPI customOpenAPI(@Value("${springdoc.version}") String appVersion) {
      +   return new OpenAPI()
      +    .components(new Components().addSecuritySchemes("basicScheme",
      +            new SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("basic")))
      +    .info(new Info().title("SpringShop API").version(appVersion)
      +            .license(new License().name("Apache 2.0").url("http://springdoc.org")));
      +}
      +
      +
      +
      +
      +
        +
      • +

        If you need the definitions to appear within a specific group, and respect the conditions specified on the GroupedOpenApi, you can add OpenApiCustomizer to your GroupedOpenApi definition.

        +
      • +
      +
      +
      +
      +
      GroupedOpenApi.builder().group("users").pathsToMatch(paths).packagesToScan(packagedToMatch).addOpenApiCustomizer(customerGlobalHeaderOpenApiCustomizer())
      +                .build()
      +
      +@Bean
      +public OpenApiCustomizer customerGlobalHeaderOpenApiCustomizer() {
      +   return openApi -> openApi.path("/foo",
      +   new PathItem().get(new Operation().operationId("foo").responses(new ApiResponses()
      +   .addApiResponse("default",new ApiResponse().description("")
      +   .content(new Content().addMediaType("fatz", new MediaType()))))));
      +}
      +
      +
      +
      +
      +
      +

      12.50. Where can I find the source code of the demo applications?

      +
      + +
      +
      +
      +

      12.51. Does this library supports annotations from interfaces?

      +
      +
        +
      • +

        Yes

        +
      • +
      +
      +
      +
      +

      12.52. What is the list of the excluded parameter types?

      + +
      +
      +

      12.53. Is file upload supported ?

      +
      +
        +
      • +

        The library supports the main file types: MultipartFile, @RequestPart, FilePart

        +
      • +
      • +

        You can upload a file as follows:

        +
      • +
      +
      +
      +
      +
      import io.swagger.v3.oas.annotations.Parameter;
      +import io.swagger.v3.oas.annotations.media.Content;
      +import io.swagger.v3.oas.annotations.media.Encoding;
      +import io.swagger.v3.oas.annotations.parameters.RequestBody;
      +
      +@PostMapping(value = "/upload", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
      +public ResponseEntity<?> upload(@Parameter(description = "file") final MultipartFile file) {
      +    return null;
      +}
      +
      +@PostMapping(value = "/uploadFileWithQuery", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
      +public ResponseEntity<?> uploadFileWithQuery(@Parameter(description = "file") @RequestPart("file") final MultipartFile file,
      +        @Parameter(description = "An extra query parameter") @RequestParam String name) {
      +    return null;
      +}
      +
      +@PostMapping(value = "/uploadFileWithJson", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}, produces = {
      +        MediaType.APPLICATION_JSON_VALUE})
      +public ResponseEntity<?> uploadFileWithJson(
      +        @RequestBody(content = @Content(encoding = @Encoding(name = "jsonRequest", contentType = MediaType.APPLICATION_JSON_VALUE)))
      +        @Parameter(description = "An extra JSON payload sent with file") @RequestPart("jsonRequest") final JsonRequest jsonRequest,
      +        @RequestPart("file") final MultipartFile file) {
      +    return null;
      +}
      +
      +
      +
      +
      +
      +

      12.54. Can I use @Parameter inside @Operation annotation?

      +
      +
        +
      • +

        Yes, it’s supported

        +
      • +
      +
      +
      +
      +

      12.55. Why my parameter is marked as required?

      +
      +
        +
      • +

        Any @GetMapping parameters is marked as required, even if @RequestParam is missing.

        +
      • +
      • +

        You can add @Parameter(required=false) annotation if you need different behaviour.

        +
      • +
      • +

        Query parameters with defaultValue specified are marked as required.

        +
      • +
      +
      +
      +
      +

      12.56. How are overloaded methods with the same endpoints, but with different parameters

      +
      +
        +
      • +

        springdoc-openapi renders these methods as a single endpoint. It detects the overloaded endpoints, and generates parameters.schema.oneOf.

        +
      • +
      +
      +
      +
      +

      12.57. What is a proper way to set up Swagger UI to use provided spec.yml?

      +
      +
        +
      • +

        With this property, all the springdoc-openapi auto-configuration beans are disabled:

        +
      • +
      +
      +
      +
      +
      springdoc.api-docs.enabled=false
      +
      +
      +
      +
        +
      • +

        Then enable the minimal Beans configuration, by adding this Bean:

        +
      • +
      +
      +
      +
      +
      @Bean
      +SpringDocConfiguration springDocConfiguration(){
      +   return new SpringDocConfiguration();
      +}
      +
      +@Bean
      +SpringDocConfigProperties springDocConfigProperties() {
      +   return new SpringDocConfigProperties();
      +}
      +
      +@Bean
      +ObjectMapperProvider objectMapperProvider(SpringDocConfigProperties springDocConfigProperties){
      +    return new ObjectMapperProvider(springDocConfigProperties);
      +}
      +
      +
      +
      +
      +
        +
      • +

        Then configure, the path of your custom UI yaml file.

        +
      • +
      +
      +
      +
      +
      springdoc.swagger-ui.url=/api-docs.yaml
      +
      +
      +
      +
      +

      12.58. Is there a way to send authorization header through the @Parameter tag?

      +
      + +
      +
      +
      +

      12.59. My Rest Controller using @Controller annotation is ignored?

      +
      +
        +
      • +

        This is the default behaviour if your @Controller doesn’t have annotation @ResponseBody

        +
      • +
      • +

        You can change your controllers to @RestControllers. Or add @ResponseBody + @Controller.

        +
      • +
      • +

        If its not possible, you can configure springdoc to scan you additional controller using SpringDocUtils. For example:

        +
      • +
      +
      +
      +
      +
      static {
      +   SpringDocUtils.getConfig().addRestControllers(HelloController.class);
      +}
      +
      +
      +
      +
      +
      +

      12.60. How can I define groups using application.yml?

      +
      +
        +
      • +

        You can load groups dynamically using spring-boot configuration files.

        +
      • +
      • +

        Note that, for this usage, you don’t have to declare the GroupedOpenApi Bean.

        +
      • +
      • +

        You need to declare the following properties, under the prefix springdoc.group-configs.

        +
      • +
      • +

        For example:

        +
      • +
      +
      +
      +
      +
      springdoc.group-configs[0].group=users
      +springdoc.group-configs[0].paths-to-match=/user/**
      +springdoc.group-configs[0].packages-to-scan=test.org.springdoc.api
      +
      +
      +
      + +
      +
      +
      +

      12.61. How can I extract fields from parameter object ?

      +
      +
        +
      • +

        You can use springdoc annotation @ParameterObject.

        +
      • +
      • +

        Request parameter annotated with @ParameterObject will help adding each field of the parameter as a separate request parameter.

        +
      • +
      • +

        This is compatible with Spring MVC request parameters mapping to POJO object.

        +
      • +
      • +

        This annotation does not support nested parameter objects.

        +
      • +
      • +

        POJO object must contain getters for fields with mandatory prefix get. Otherwise, the swagger documentation will not show the fields of the annotated entity.

        +
      • +
      +
      +
      +
      +

      12.62. How can I use the last springdoc-openapi SNAPSHOT ?

      +
      +
        +
      • +

        For testing purposes only, you can test temporarily using the last springdoc-openapi SNAPSHOT

        +
      • +
      • +

        To achieve that, configure your pom.xml file with the following <repositories> section:

        +
      • +
      +
      +
      +
      +
          <repositories>
      +      <repository>
      +        <name>Central Portal Snapshots</name>
      +        <id>central-portal-snapshots</id>
      +        <url>https://central.sonatype.com/repository/maven-snapshots/</url>
      +        <releases>
      +          <enabled>false</enabled>
      +        </releases>
      +        <snapshots>
      +          <enabled>true</enabled>
      +        </snapshots>
      +      </repository>
      +    </repositories>
      +
      +
      +
      +
      +

      12.63. How can I use enable springdoc-openapi MonetaryAmount support ?

      +
      +
        +
      • +

        If an application wants to enable the springdoc-openapi support, it declares:

        +
      • +
      +
      +
      +
      +
      SpringDocUtils.getConfig().replaceWithClass(MonetaryAmount.class, org.springdoc.core.converters.models.MonetaryAmount.class);
      +
      +
      +
      +
      +
        +
      • +

        Another solution, without using springdoc-openapi MonetaryAmount, would be:

        +
      • +
      +
      +
      +
      +
      SpringDocUtils.getConfig().replaceWithSchema(MonetaryAmount.class, new ObjectSchema()
      +            .addProperties("amount", new NumberSchema()).example(99.96)
      +            .addProperties("currency", new StringSchema().example("USD")));
      +
      +
      +
      +
      +
      +

      12.64. How can i aggregate external endpoints (exposing OPENAPI 3 spec) inside one single application?

      +
      +

      The properties springdoc.swagger-ui.urls.*, are suitable to configure external (/v3/api-docs url). +For example if you want to agreagte all the endpoints of other services, inside one single application. +IMPORTANT: Don’t forget that CORS needs to be enabled as well.

      +
      +
      +
      +

      12.65. How can use custom json/yml file instead of generated one ?

      +
      +

      If your file open-api.json, contains the OpenAPI documentation in OpenAPI 3 format. +Then simply declare: The file name can be anything you want, from the moment your declaration is consistent yaml or json OpenAPI Spec.

      +
      +
      +
      +
         springdoc.swagger-ui.url=/open-api.json
      +
      +
      +
      +

      Then the file open-api.json, should be located in: src/main/resources/static +No additional configuration is needed.

      +
      +
      +
      +

      12.66. How can i enable CSRF support?

      +
      +

      If you are using standard headers.( For example using spring-security headers) +If the CSRF Token is required, swagger-ui automatically sends the new XSRF-TOKEN during each HTTP REQUEST.

      +
      +
      +

      If your XSRF-TOKEN isn’t standards-based, you can use a requestInterceptor to manually capture and attach the latest xsrf token to requests programmatically via spring resource transformer:

      +
      + +
      +

      Starting from release v1.4.4 of springdoc-openapi, a new property is added to enable CSRF support, while using standard header names:

      +
      +
      +
      +
      springdoc.swagger-ui.csrf.enabled=true
      +
      +
      +
      +
      +

      12.67. How can i disable the default swagger petstore URL?

      +
      +

      You can use the following property:

      +
      +
      +
      +
      springdoc.swagger-ui.disable-swagger-default-url=true
      +
      +
      +
      +
      +

      12.68. Is @PageableDefault supported, to enhance the OpenAPI 3 docuementation?

      +
      +

      Yes, you can use it in conjunction with @ParameterObject annotation. +Also, the spring-boot spring.data.web. and spring.data.rest.default. properties are supported since v1.4.5

      +
      +
      +
      +

      12.69. How can i make spring security login-endpoint visible ?

      +
      +

      You can use the following property:

      +
      +
      +
      +
      springdoc.show-login-endpoint=true
      +
      +
      +
      +
      +

      12.70. How can i show schema definitions even the schema is not referenced?

      +
      +

      You can use the following property:

      +
      +
      +
      +
      springdoc.remove-broken-reference-definitions=false
      +
      +
      +
      +
      +

      12.71. How to override @Deprecated?

      +
      +

      The whole idea of springdoc-openapi is to get your documentation the closest to the code, with minimal code changes. +If the code contains @Deprecated, sprindoc-openapi will consider its schema as Deprecated as well. +If you want to declare a field on swagger as non deprecated, even with the java code, the field contains @Depreacted, +You can use the following property that is available since release v1.4.3:

      +
      +
      +
      +
      springdoc.model-converters.deprecating-converter.enabled=false
      +
      +
      +
      +
      +

      12.72. How can i display a method that returns ModelAndView?

      +
      +

      You can use the following property:

      +
      +
      +
      +
      springdoc.model-and-view-allowed=true
      +
      +
      +
      +
      +

      12.73. How can i have pretty-printed output of the OpenApi specification?

      +
      +

      You can use the following property:

      +
      +
      +
      +
      springdoc.writer-with-default-pretty-printer=true
      +
      +
      +
      +
      +

      12.74. How can i define different schemas for the same class?

      +
      +

      Complex objects are always resolved as a reference to a schema defined in components. +For example let’s consider a Instance class with an workAddress and homeAddress attribute of type Address:

      +
      +
      +
      +
      public class PersonDTO {
      +
      +    @JsonProperty
      +    private String email;
      +
      +    @JsonProperty
      +    private String firstName;
      +
      +    @JsonProperty
      +    private String lastName;
      +
      +    @Schema(ref = "WorkAddressSchema")
      +    @JsonProperty
      +    private Address workAddress;
      +
      +    @Schema(ref = "HomeAddressSchema")
      +    @JsonProperty
      +    private Address homeAddress;
      +
      +}
      +
      +public class Address {
      +
      +    @JsonProperty
      +    private String addressName;
      +
      +}
      +
      +
      +
      +
      +

      If you want to define two different schemas for this class, you can set up 2 different schemas as follow:

      +
      +
      +
      +
      @Bean
      +public OpenAPI customOpenAPI() {
      +return new OpenAPI().components(new Components()
      +.addSchemas("WorkAddressSchema", getSchemaWithDifferentDescription(Address.class, "work Address" ))
      +.addSchemas("HomeAddressSchema", getSchemaWithDifferentDescription(Address.class, "home Address" )));
      +}
      +
      +private Schema getSchemaWithDifferentDescription(Class className, String description){
      +ResolvedSchema resolvedSchema = ModelConverters.getInstance()
      +.resolveAsResolvedSchema(
      +new AnnotatedType(className).resolveAsRef(false));
      +return resolvedSchema.schema.description(description);
      +}
      +
      +
      +
      +
      +
      +

      12.75. How can i define different description for a class attribute depending on usage?

      +
      +

      For example let’s consider a Instance class with an email attribute:

      +
      +
      +
      +
      public class PersonDTO {
      +
      +    @JsonProperty
      +    private String email;
      +
      +    @JsonProperty
      +    private String firstName;
      +
      +    @JsonProperty
      +    private String lastName;
      +
      +
      +}
      +
      +
      +
      +
      +

      If you want to define two different description for the email, you can set up 2 different schemas as follow:

      +
      +
      +
      +
      @Bean
      +public OpenAPI customOpenAPI() {
      +return new OpenAPI().components(new Components()
      +.addSchemas("PersonDTO1", getFieldSchemaWithDifferentDescription(PersonDTO.class, "work email" ))
      +.addSchemas("PersonDTO2", getFieldSchemaWithDifferentDescription(PersonDTO.class, "home email" )));
      +}
      +
      +private Schema getFieldSchemaWithDifferentDescription(Class className, String description){
      +    ResolvedSchema resolvedSchema = ModelConverters.getInstance()
      +            .resolveAsResolvedSchema(
      +                    new AnnotatedType(className).resolveAsRef(false));
      +    return resolvedSchema.schema.addProperties("email", new StringSchema().description(description));
      +}
      +
      +
      +
      +
      +
      +

      12.76. Customizing swagger static resources

      +
      +

      You can customize swagger documentation static resources located in META-INF/resources/webjars/swagger-ui/{swagger.version}/. The list of resources includes:

      +
      +
      +
        +
      • +

        index.html

        +
      • +
      • +

        swagger-ui-bundle.js

        +
      • +
      • +

        swagger-ui.css

        +
      • +
      • +

        swagger-ui-standalone-preset.js

        +
      • +
      • +

        swagger-ui.css.map

        +
      • +
      • +

        swagger-ui-bundle.js.map

        +
      • +
      • +

        swagger-ui-standalone-preset.js.map

        +
      • +
      • +

        favicon-32x32.png

        +
      • +
      +
      +
      +

      To do this, you need to extend the implementation of SwaggerIndexPageTransformer

      +
      +
      +
      +
      public class SwaggerCodeBlockTransformer
      +       extends SwaggerIndexPageTransformer {
      +  // < constructor >
      +  @Override
      +  public Resource transform(HttpServletRequest request,
      +                            Resource resource,
      +                            ResourceTransformerChain transformer)
      +                            throws IOException {
      +      if (resource.toString().contains("swagger-ui.css")) {
      +          final InputStream is = resource.getInputStream();
      +          final InputStreamReader isr = new InputStreamReader(is);
      +          try (BufferedReader br = new BufferedReader(isr)) {
      +              final String css = br.lines().collect(Collectors.joining());
      +              final byte[] transformedContent = css.replace("old", "new").getBytes();
      +              return  new TransformedResource(resource, transformedContent);
      +          } // AutoCloseable br > isr > is
      +      }
      +      return super.transform(request, resource, transformer);
      +  }
      +
      +}
      +
      +
      +
      +
      +

      Next, add transformer @Bean to your @Configuration

      +
      +
      +
      +
      @Configuration
      +public class OpenApiConfig {
      +    @Bean
      +    public SwaggerIndexTransformer swaggerIndexTransformer(
      +            SwaggerUiConfigProperties a,
      +            SwaggerUiOAuthProperties b,
      +            SwaggerUiConfigParameters c,
      +            SwaggerWelcomeCommon d) {
      +        return new SwaggerCodeBlockTransformer(a, b, c, d);
      +    }
      +}
      +
      +
      +
      +
      +

      Illustrative example

      +
      +
      +
      +Illustrative example +
      +
      +
      +
      +

      12.77. Is GraalVM supported ?

      +
      +

      The native support available added in spring-boot 3. +If you have some time, do not hesitate to test it before the next release.

      +
      +
      +

      For the OpenAPI REST endpoints, you just need to build your application with the spring native profile.

      +
      +
      +

      If you give @OpenAPIDefinition or @SecurityScheme to a class that has no implementation, that class will disappear when you natively compile. +To avoid this, give the class a @Configuration.

      +
      +
      +
      +
      @Configuration
      +@OpenAPIDefinition(info = @Info(title = "My App", description = "description"))
      +public class OpenAPIConfig {
      +}
      +
      +
      +
      +
      +

      12.78. How to Integrate Open API 3 with Spring project (not Spring Boot)?

      +
      +

      When your application is using spring without (spring-boot), you need to add beans and auto-configuration that are natively provided in spring-boot.

      +
      +
      +

      For example, lets assume you want load the swagger-ui in spring-mvc application:

      +
      +
      +
        +
      • +

        You mainly, need to add the springdoc-openapi module

        +
      • +
      +
      +
      +
      +
      <dependency>
      +   <groupId>org.springdoc</groupId>
      +   <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
      +   <version>last.version</version>
      +</dependency>
      +
      +
      +
      +
        +
      • +

        If you don’t have the spring-boot and spring-boot-autoconfigure dependencies, you need to add them. And pay attention to the compatibility matrix, between you spring.version and spring-boot.version. For example, in this case (spring.version=5.1.12.RELEASE):

        +
      • +
      +
      +
      +
      +
              <dependency>
      +            <groupId>org.springframework.boot</groupId>
      +            <artifactId>spring-boot-autoconfigure</artifactId>
      +            <version>3.3.3</version>
      +        </dependency>
      +
      +
      +
      +
        +
      • +

        Scan for the springdoc-openapi 'auto-configuration classes that spring-boot automatically loads for you.

        +
      • +
      • +

        Depending on your module, you can find them on the file: spring.factories of each springdoc-openapi module.

        +
      • +
      +
      +
      +
      +
      @Configuration
      +@EnableWebMvc
      +public class WebConfig implements WebApplicationInitializer {
      +
      +    @Override
      +    public void onStartup(ServletContext servletContext)  {
      +        WebApplicationContext context = getContext();
      +        servletContext.addListener(new ContextLoaderListener(context));
      +        ServletRegistration.Dynamic dispatcher = servletContext.addServlet("RestServlet",
      +                new DispatcherServlet(context));
      +        dispatcher.setLoadOnStartup(1);
      +        dispatcher.addMapping("/*");
      +    }
      +
      +    private AnnotationConfigWebApplicationContext getContext() {
      +        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
      +        context.register(this.getClass(),
      +                SpringDocConfiguration.class,
      +                SpringDocConfigProperties.class,
      +                SpringDocSpecPropertiesConfiguration.class,
      +                SpringDocWebMvcConfiguration.class,
      +                MultipleOpenApiSupportConfiguration.class,
      +                SwaggerConfig.class,
      +                SwaggerUiConfigProperties.class,
      +                SwaggerUiOAuthProperties.class,
      +        );
      +        return context;
      +    }
      +}
      +
      +
      +
      +
      +
        +
      • +

        Depending on your module, you can find them on the file: org.springframework.boot.autoconfigure.AutoConfiguration.imports of each springdoc-openapi module.

        +
      • +
      • +

        For groups usage make sure your GroupedOpenApi Beans are scanned.

        +
      • +
      • +

        If additionally, you are using custom context path: /my-servlet-path. Make sure you declare the following property:

        +
      • +
      +
      +
      +
      +
      spring.mvc.servlet.path=/my-servlet-path
      +
      +
      +
      +
      +

      12.79. What is the compatibility matrix of springdoc-openapi with spring-boot ?

      +
      +

      springdoc-openapi 3.x is compatible with spring-boot 4.

      +
      +
      +

      In general, you should only pick the last stable version as per today 3.0.0-M1.

      +
      +
      +

      More precisely, this the exhaustive list of spring-boot versions against which springdoc-openapi has been built:

      +
      + ++++ + + + + + + + + + + +

      Spring Boot Versions

      Springdoc OpenAPI Versions

      4.0.x

      3.0.x

      +
      +
      +

      12.80. Why am i getting an error: Swagger UI unable to render definition, when overriding the default spring registered HttpMessageConverter?

      +
      +

      When overriding the default spring-boot registered HttpMessageConverter, you should have ByteArrayHttpMessageConverter registered as well to have proper springdoc-openapi support.

      +
      +
      +
      +
          converters.add(new ByteArrayHttpMessageConverter());
      +    converters.add(new MappingJackson2HttpMessageConverter(jacksonBuilder.build()));
      +
      +
      +
      +
      + + + + + +
      + + +Order is very important, when registering HttpMessageConverters. +
      +
      +
      +
      +

      12.81. Some parameters are not generated in the resulting OpenAPI spec.

      +
      +

      The issue is caused by the changes introduced by Spring-Boot 3.2.0 +in particular for the Parameter Name Discovery. +This can be fixed by adding the -parameters arg to the Maven Compiler Plugin.

      +
      +
      +
      +
      <plugin>
      +    <groupId>org.apache.maven.plugins</groupId>
      +    <artifactId>maven-compiler-plugin</artifactId>
      +    <configuration>
      +        <parameters>true</parameters>
      +    </configuration>
      +</plugin>
      +
      +
      +
      +
      +
      +
      + +
      +
      +
      + + \ No newline at end of file diff --git a/docs/v4/intro.html b/docs/v4/intro.html new file mode 100644 index 0000000..25186c4 --- /dev/null +++ b/docs/v4/intro.html @@ -0,0 +1,91 @@ + + + + + + + +Introduction + + + + + + +
      +
      +
      + +
      +
      +

      Introduction

      +
      +
      +

      springdoc-openapi java library helps to automate the generation of API documentation using spring boot projects. +springdoc-openapi works by examining an application at runtime to infer API semantics based on spring configurations, class structure and various annotations.

      +
      +
      +

      Automatically generates documentation in JSON/YAML and HTML format APIs. +This documentation can be completed by comments using swagger-api annotations.

      +
      +
      +

      This library supports:

      +
      +
      +
        +
      • +

        OpenAPI 3

        +
      • +
      • +

        Spring-boot v4 (Java 17 & Jakarta EE 9)

        +
      • +
      • +

        JSR-303, specifically for @NotNull, @Min, @Max, and @Size.

        +
      • +
      • +

        Swagger-ui

        +
      • +
      • +

        OAuth 2

        +
      • +
      • +

        GraalVM native images

        +
      • +
      +
      +
      +

      The following video introduces the Library:

      +
      +
      +
      +spring.io conference +
      +
      +
      +

      This is a community-based project, not maintained by the Spring Framework Contributors (Pivotal).

      +
      +
      +
      +
      + +
      +
      +
      + + \ No newline at end of file diff --git a/docs/v4/js/setup.js b/docs/v4/js/setup.js new file mode 100644 index 0000000..ae5b1b7 --- /dev/null +++ b/docs/v4/js/setup.js @@ -0,0 +1,3 @@ +!function(){"use strict";document.getElementsByTagName("html")[0].classList.add("js")}(); +!function(){var t=function(t,n,e){if("function"!=typeof t)throw new TypeError("Expected a function");return setTimeout((function(){t.apply(void 0,e)}),n)};var n=function(t){return t};var e=function(t,n,e){switch(e.length){case 0:return t.call(n);case 1:return t.call(n,e[0]);case 2:return t.call(n,e[0],e[1]);case 3:return t.call(n,e[0],e[1],e[2])}return t.apply(n,e)},r=Math.max;var o=function(t,n,o){return n=r(void 0===n?t.length-1:n,0),function(){for(var c=arguments,u=-1,i=r(c.length-n,0),a=Array(i);++u0){if(++n>=800)return arguments[0]}else n=0;return t.apply(void 0,arguments)}},D=C(R);var G=/\s/;var U=function(t){for(var n=t.length;n--&&G.test(t.charAt(n)););return n},z=/^\s+/;var B=function(t){return t?t.slice(0,U(t)+1).replace(z,""):t};var H=function(t){return null!=t&&"object"==typeof t};var J=function(t){return"symbol"==typeof t||H(t)&&"[object Symbol]"==g(t)},K=/^[-+]0x[0-9a-f]+$/i,Q=/^0b[01]+$/i,V=/^0o[0-7]+$/i,W=parseInt;var X=function(t){if("number"==typeof t)return t;if(J(t))return NaN;if(m(t)){var n="function"==typeof t.valueOf?t.valueOf():t;t=m(n)?n+"":n}if("string"!=typeof t)return 0===t?t:+t;t=B(t);var e=Q.test(t);return e||V.test(t)?W(t.slice(2),e?2:8):K.test(t)?NaN:+t},Y=function(t,e){return D(o(t,e,n),t+"")}((function(n,e,r){return t(n,X(e)||0,r)}));!function(){"use strict";const t=window.localStorage,n=document.documentElement,e=window.matchMedia("(prefers-color-scheme: dark)");function r(){const n=null!==t?t.getItem("theme"):null;return n?"dark"===n:e.matches}function o(){this.checked?(Y((function(){n.classList.add("dark-theme")}),100),c("dark")):(Y((function(){n.classList.remove("dark-theme")}),100),c("light"))}function c(n){t&&t.setItem("theme",n)}r()&&n.classList.add("dark-theme"),window.addEventListener("load",(function(){const t=document.querySelector("#switch-theme-checkbox");t.checked=r(),t.addEventListener("change",o.bind(t))}))}()}(); +//# sourceMappingURL=setup.js.map diff --git a/docs/v4/js/setup.js.map b/docs/v4/js/setup.js.map new file mode 100644 index 0000000..2971105 --- /dev/null +++ b/docs/v4/js/setup.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["setup/src/main/js/setup/layout.js","setup/node_modules/browser-pack-flat/_prelude","setup/node_modules/lodash/_baseDelay.js","setup/switchtheme.js","setup/node_modules/lodash/identity.js","setup/node_modules/lodash/_apply.js","setup/node_modules/lodash/_overRest.js","setup/node_modules/lodash/constant.js","setup/node_modules/lodash/_freeGlobal.js","setup/node_modules/lodash/_root.js","setup/node_modules/lodash/_Symbol.js","setup/node_modules/lodash/_getRawTag.js","setup/node_modules/lodash/_objectToString.js","setup/node_modules/lodash/_baseGetTag.js","setup/node_modules/lodash/isObject.js","setup/node_modules/lodash/isFunction.js","setup/node_modules/lodash/_isMasked.js","setup/node_modules/lodash/_coreJsData.js","setup/node_modules/lodash/_toSource.js","setup/node_modules/lodash/_baseIsNative.js","setup/node_modules/lodash/_getValue.js","setup/node_modules/lodash/_getNative.js","setup/node_modules/lodash/_defineProperty.js","setup/node_modules/lodash/_baseSetToString.js","setup/node_modules/lodash/_shortOut.js","setup/node_modules/lodash/_setToString.js","setup/node_modules/lodash/_baseRest.js","setup/node_modules/lodash/_trimmedEndIndex.js","setup/node_modules/lodash/_baseTrim.js","setup/node_modules/lodash/isObjectLike.js","setup/node_modules/lodash/isSymbol.js","setup/node_modules/lodash/toNumber.js","setup/node_modules/lodash/delay.js","setup/src/main/js/setup/switchtheme.js","setup/node_modules/browser-pack-flat/_postlude"],"names":["document","getElementsByTagName","classList","add","_$baseDelay_3","func","wait","args","TypeError","setTimeout","apply","undefined","_$identity_25","value","_$apply_2","thisArg","length","call","nativeMax","Math","max","_$overRest_17","start","transform","arguments","index","array","Array","otherArgs","this","_$constant_23","_$freeGlobal_11","global","freeGlobal","Object","self","window","freeSelf","_$root_18","Function","_$Symbol_1","Symbol","objectProto","prototype","hasOwnProperty","nativeObjectToString","toString","symToStringTag","toStringTag","_$getRawTag_13","isOwn","tag","unmasked","e","result","__nativeObjectToString_16","_$objectToString_16","__symToStringTag_4","_$baseGetTag_4","_$isObject_27","type","uid","_$isFunction_26","_$coreJsData_9","maskSrcKey","exec","keys","IE_PROTO","_$isMasked_15","funcToString","_$toSource_21","reIsHostCtor","__funcProto_5","__objectProto_5","__funcToString_5","__hasOwnProperty_5","reIsNative","RegExp","replace","_$baseIsNative_5","test","_$getValue_14","object","key","_$getNative_12","_$defineProperty_10","_$baseSetToString_7","string","configurable","enumerable","writable","nativeNow","Date","now","_$shortOut_20","count","lastCalled","stamp","remaining","_$setToString_19","reWhitespace","_$trimmedEndIndex_22","charAt","reTrimStart","_$baseTrim_8","slice","_$isObjectLike_28","_$isSymbol_29","reIsBadHex","reIsBinary","reIsOctal","freeParseInt","parseInt","_$toNumber_30","other","valueOf","isBinary","_$delay_24","_$baseRest_6","localStorage","htmlElement","documentElement","prefersDarkColorScheme","matchMedia","isInitialThemeDark","theme","getItem","matches","onThemeChange","checked","saveTheme","remove","setItem","addEventListener","toggleCheckboxElement","querySelector","bind"],"mappings":"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","file":"setup.js","sourcesContent":["/*\n * Copyright 2021 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the 'License');\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an 'AS IS' BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n(function () {\n \"use strict\";\n document.getElementsByTagName(\"html\")[0].classList.add(\"js\");\n})();\n","(function(){\n","/** Error message constants. */\nvar FUNC_ERROR_TEXT = 'Expected a function';\n\n/**\n * The base implementation of `_.delay` and `_.defer` which accepts `args`\n * to provide to `func`.\n *\n * @private\n * @param {Function} func The function to delay.\n * @param {number} wait The number of milliseconds to delay invocation.\n * @param {Array} args The arguments to provide to `func`.\n * @returns {number|Object} Returns the timer id or timeout object.\n */\nfunction baseDelay(func, wait, args) {\n if (typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n return setTimeout(function() { func.apply(undefined, args); }, wait);\n}\n\nmodule.exports = baseDelay;\n","/*\n * Copyright 2021 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the 'License');\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an 'AS IS' BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n(function () {\n \"use strict\";\n\n const delay = require(\"lodash/delay\");\n\n const localStorage = window.localStorage;\n const htmlElement = document.documentElement;\n const prefersDarkColorScheme = window.matchMedia(\n \"(prefers-color-scheme: dark)\"\n );\n\n swithInitialTheme();\n window.addEventListener(\"load\", onWindowLoad);\n\n function swithInitialTheme() {\n if (isInitialThemeDark()) {\n htmlElement.classList.add(\"dark-theme\");\n }\n }\n\n function onWindowLoad() {\n const toggleCheckboxElement = document.querySelector(\n \"#switch-theme-checkbox\"\n );\n toggleCheckboxElement.checked = isInitialThemeDark();\n toggleCheckboxElement.addEventListener(\n \"change\",\n onThemeChange.bind(toggleCheckboxElement)\n );\n }\n\n function isInitialThemeDark() {\n const theme = loadTheme();\n return theme ? theme === \"dark\" : prefersDarkColorScheme.matches;\n }\n\n function onThemeChange() {\n if (this.checked) {\n delay(function () {\n htmlElement.classList.add(\"dark-theme\");\n }, 100);\n saveTheme(\"dark\");\n } else {\n delay(function () {\n htmlElement.classList.remove(\"dark-theme\");\n }, 100);\n saveTheme(\"light\");\n }\n }\n\n function saveTheme(theme) {\n if (localStorage) {\n localStorage.setItem(\"theme\", theme);\n }\n }\n\n function loadTheme() {\n return localStorage !== null ? localStorage.getItem(\"theme\") : null;\n }\n})();\n","/**\n * This method returns the first argument it receives.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Util\n * @param {*} value Any value.\n * @returns {*} Returns `value`.\n * @example\n *\n * var object = { 'a': 1 };\n *\n * console.log(_.identity(object) === object);\n * // => true\n */\nfunction identity(value) {\n return value;\n}\n\nmodule.exports = identity;\n","/**\n * A faster alternative to `Function#apply`, this function invokes `func`\n * with the `this` binding of `thisArg` and the arguments of `args`.\n *\n * @private\n * @param {Function} func The function to invoke.\n * @param {*} thisArg The `this` binding of `func`.\n * @param {Array} args The arguments to invoke `func` with.\n * @returns {*} Returns the result of `func`.\n */\nfunction apply(func, thisArg, args) {\n switch (args.length) {\n case 0: return func.call(thisArg);\n case 1: return func.call(thisArg, args[0]);\n case 2: return func.call(thisArg, args[0], args[1]);\n case 3: return func.call(thisArg, args[0], args[1], args[2]);\n }\n return func.apply(thisArg, args);\n}\n\nmodule.exports = apply;\n","var apply = require('./_apply');\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max;\n\n/**\n * A specialized version of `baseRest` which transforms the rest array.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @param {Function} transform The rest array transform.\n * @returns {Function} Returns the new function.\n */\nfunction overRest(func, start, transform) {\n start = nativeMax(start === undefined ? (func.length - 1) : start, 0);\n return function() {\n var args = arguments,\n index = -1,\n length = nativeMax(args.length - start, 0),\n array = Array(length);\n\n while (++index < length) {\n array[index] = args[start + index];\n }\n index = -1;\n var otherArgs = Array(start + 1);\n while (++index < start) {\n otherArgs[index] = args[index];\n }\n otherArgs[start] = transform(array);\n return apply(func, this, otherArgs);\n };\n}\n\nmodule.exports = overRest;\n","/**\n * Creates a function that returns `value`.\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Util\n * @param {*} value The value to return from the new function.\n * @returns {Function} Returns the new constant function.\n * @example\n *\n * var objects = _.times(2, _.constant({ 'a': 1 }));\n *\n * console.log(objects);\n * // => [{ 'a': 1 }, { 'a': 1 }]\n *\n * console.log(objects[0] === objects[1]);\n * // => true\n */\nfunction constant(value) {\n return function() {\n return value;\n };\n}\n\nmodule.exports = constant;\n","/** Detect free variable `global` from Node.js. */\nvar freeGlobal = typeof global == 'object' && global && global.Object === Object && global;\n\nmodule.exports = freeGlobal;\n","var freeGlobal = require('./_freeGlobal');\n\n/** Detect free variable `self`. */\nvar freeSelf = typeof self == 'object' && self && self.Object === Object && self;\n\n/** Used as a reference to the global object. */\nvar root = freeGlobal || freeSelf || Function('return this')();\n\nmodule.exports = root;\n","var root = require('./_root');\n\n/** Built-in value references. */\nvar Symbol = root.Symbol;\n\nmodule.exports = Symbol;\n","var Symbol = require('./_Symbol');\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/** Built-in value references. */\nvar symToStringTag = Symbol ? Symbol.toStringTag : undefined;\n\n/**\n * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the raw `toStringTag`.\n */\nfunction getRawTag(value) {\n var isOwn = hasOwnProperty.call(value, symToStringTag),\n tag = value[symToStringTag];\n\n try {\n value[symToStringTag] = undefined;\n var unmasked = true;\n } catch (e) {}\n\n var result = nativeObjectToString.call(value);\n if (unmasked) {\n if (isOwn) {\n value[symToStringTag] = tag;\n } else {\n delete value[symToStringTag];\n }\n }\n return result;\n}\n\nmodule.exports = getRawTag;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\nfunction objectToString(value) {\n return nativeObjectToString.call(value);\n}\n\nmodule.exports = objectToString;\n","var Symbol = require('./_Symbol'),\n getRawTag = require('./_getRawTag'),\n objectToString = require('./_objectToString');\n\n/** `Object#toString` result references. */\nvar nullTag = '[object Null]',\n undefinedTag = '[object Undefined]';\n\n/** Built-in value references. */\nvar symToStringTag = Symbol ? Symbol.toStringTag : undefined;\n\n/**\n * The base implementation of `getTag` without fallbacks for buggy environments.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the `toStringTag`.\n */\nfunction baseGetTag(value) {\n if (value == null) {\n return value === undefined ? undefinedTag : nullTag;\n }\n return (symToStringTag && symToStringTag in Object(value))\n ? getRawTag(value)\n : objectToString(value);\n}\n\nmodule.exports = baseGetTag;\n","/**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\nfunction isObject(value) {\n var type = typeof value;\n return value != null && (type == 'object' || type == 'function');\n}\n\nmodule.exports = isObject;\n","var baseGetTag = require('./_baseGetTag'),\n isObject = require('./isObject');\n\n/** `Object#toString` result references. */\nvar asyncTag = '[object AsyncFunction]',\n funcTag = '[object Function]',\n genTag = '[object GeneratorFunction]',\n proxyTag = '[object Proxy]';\n\n/**\n * Checks if `value` is classified as a `Function` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a function, else `false`.\n * @example\n *\n * _.isFunction(_);\n * // => true\n *\n * _.isFunction(/abc/);\n * // => false\n */\nfunction isFunction(value) {\n if (!isObject(value)) {\n return false;\n }\n // The use of `Object#toString` avoids issues with the `typeof` operator\n // in Safari 9 which returns 'object' for typed arrays and other constructors.\n var tag = baseGetTag(value);\n return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;\n}\n\nmodule.exports = isFunction;\n","var coreJsData = require('./_coreJsData');\n\n/** Used to detect methods masquerading as native. */\nvar maskSrcKey = (function() {\n var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');\n return uid ? ('Symbol(src)_1.' + uid) : '';\n}());\n\n/**\n * Checks if `func` has its source masked.\n *\n * @private\n * @param {Function} func The function to check.\n * @returns {boolean} Returns `true` if `func` is masked, else `false`.\n */\nfunction isMasked(func) {\n return !!maskSrcKey && (maskSrcKey in func);\n}\n\nmodule.exports = isMasked;\n","var root = require('./_root');\n\n/** Used to detect overreaching core-js shims. */\nvar coreJsData = root['__core-js_shared__'];\n\nmodule.exports = coreJsData;\n","/** Used for built-in method references. */\nvar funcProto = Function.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/**\n * Converts `func` to its source code.\n *\n * @private\n * @param {Function} func The function to convert.\n * @returns {string} Returns the source code.\n */\nfunction toSource(func) {\n if (func != null) {\n try {\n return funcToString.call(func);\n } catch (e) {}\n try {\n return (func + '');\n } catch (e) {}\n }\n return '';\n}\n\nmodule.exports = toSource;\n","var isFunction = require('./isFunction'),\n isMasked = require('./_isMasked'),\n isObject = require('./isObject'),\n toSource = require('./_toSource');\n\n/**\n * Used to match `RegExp`\n * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).\n */\nvar reRegExpChar = /[\\\\^$.*+?()[\\]{}|]/g;\n\n/** Used to detect host constructors (Safari). */\nvar reIsHostCtor = /^\\[object .+?Constructor\\]$/;\n\n/** Used for built-in method references. */\nvar funcProto = Function.prototype,\n objectProto = Object.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Used to detect if a method is native. */\nvar reIsNative = RegExp('^' +\n funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\\\$&')\n .replace(/hasOwnProperty|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g, '$1.*?') + '$'\n);\n\n/**\n * The base implementation of `_.isNative` without bad shim checks.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a native function,\n * else `false`.\n */\nfunction baseIsNative(value) {\n if (!isObject(value) || isMasked(value)) {\n return false;\n }\n var pattern = isFunction(value) ? reIsNative : reIsHostCtor;\n return pattern.test(toSource(value));\n}\n\nmodule.exports = baseIsNative;\n","/**\n * Gets the value at `key` of `object`.\n *\n * @private\n * @param {Object} [object] The object to query.\n * @param {string} key The key of the property to get.\n * @returns {*} Returns the property value.\n */\nfunction getValue(object, key) {\n return object == null ? undefined : object[key];\n}\n\nmodule.exports = getValue;\n","var baseIsNative = require('./_baseIsNative'),\n getValue = require('./_getValue');\n\n/**\n * Gets the native function at `key` of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {string} key The key of the method to get.\n * @returns {*} Returns the function if it's native, else `undefined`.\n */\nfunction getNative(object, key) {\n var value = getValue(object, key);\n return baseIsNative(value) ? value : undefined;\n}\n\nmodule.exports = getNative;\n","var getNative = require('./_getNative');\n\nvar defineProperty = (function() {\n try {\n var func = getNative(Object, 'defineProperty');\n func({}, '', {});\n return func;\n } catch (e) {}\n}());\n\nmodule.exports = defineProperty;\n","var constant = require('./constant'),\n defineProperty = require('./_defineProperty'),\n identity = require('./identity');\n\n/**\n * The base implementation of `setToString` without support for hot loop shorting.\n *\n * @private\n * @param {Function} func The function to modify.\n * @param {Function} string The `toString` result.\n * @returns {Function} Returns `func`.\n */\nvar baseSetToString = !defineProperty ? identity : function(func, string) {\n return defineProperty(func, 'toString', {\n 'configurable': true,\n 'enumerable': false,\n 'value': constant(string),\n 'writable': true\n });\n};\n\nmodule.exports = baseSetToString;\n","/** Used to detect hot functions by number of calls within a span of milliseconds. */\nvar HOT_COUNT = 800,\n HOT_SPAN = 16;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeNow = Date.now;\n\n/**\n * Creates a function that'll short out and invoke `identity` instead\n * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`\n * milliseconds.\n *\n * @private\n * @param {Function} func The function to restrict.\n * @returns {Function} Returns the new shortable function.\n */\nfunction shortOut(func) {\n var count = 0,\n lastCalled = 0;\n\n return function() {\n var stamp = nativeNow(),\n remaining = HOT_SPAN - (stamp - lastCalled);\n\n lastCalled = stamp;\n if (remaining > 0) {\n if (++count >= HOT_COUNT) {\n return arguments[0];\n }\n } else {\n count = 0;\n }\n return func.apply(undefined, arguments);\n };\n}\n\nmodule.exports = shortOut;\n","var baseSetToString = require('./_baseSetToString'),\n shortOut = require('./_shortOut');\n\n/**\n * Sets the `toString` method of `func` to return `string`.\n *\n * @private\n * @param {Function} func The function to modify.\n * @param {Function} string The `toString` result.\n * @returns {Function} Returns `func`.\n */\nvar setToString = shortOut(baseSetToString);\n\nmodule.exports = setToString;\n","var identity = require('./identity'),\n overRest = require('./_overRest'),\n setToString = require('./_setToString');\n\n/**\n * The base implementation of `_.rest` which doesn't validate or coerce arguments.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @returns {Function} Returns the new function.\n */\nfunction baseRest(func, start) {\n return setToString(overRest(func, start, identity), func + '');\n}\n\nmodule.exports = baseRest;\n","/** Used to match a single whitespace character. */\nvar reWhitespace = /\\s/;\n\n/**\n * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace\n * character of `string`.\n *\n * @private\n * @param {string} string The string to inspect.\n * @returns {number} Returns the index of the last non-whitespace character.\n */\nfunction trimmedEndIndex(string) {\n var index = string.length;\n\n while (index-- && reWhitespace.test(string.charAt(index))) {}\n return index;\n}\n\nmodule.exports = trimmedEndIndex;\n","var trimmedEndIndex = require('./_trimmedEndIndex');\n\n/** Used to match leading whitespace. */\nvar reTrimStart = /^\\s+/;\n\n/**\n * The base implementation of `_.trim`.\n *\n * @private\n * @param {string} string The string to trim.\n * @returns {string} Returns the trimmed string.\n */\nfunction baseTrim(string) {\n return string\n ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '')\n : string;\n}\n\nmodule.exports = baseTrim;\n","/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return value != null && typeof value == 'object';\n}\n\nmodule.exports = isObjectLike;\n","var baseGetTag = require('./_baseGetTag'),\n isObjectLike = require('./isObjectLike');\n\n/** `Object#toString` result references. */\nvar symbolTag = '[object Symbol]';\n\n/**\n * Checks if `value` is classified as a `Symbol` primitive or object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.\n * @example\n *\n * _.isSymbol(Symbol.iterator);\n * // => true\n *\n * _.isSymbol('abc');\n * // => false\n */\nfunction isSymbol(value) {\n return typeof value == 'symbol' ||\n (isObjectLike(value) && baseGetTag(value) == symbolTag);\n}\n\nmodule.exports = isSymbol;\n","var baseTrim = require('./_baseTrim'),\n isObject = require('./isObject'),\n isSymbol = require('./isSymbol');\n\n/** Used as references for various `Number` constants. */\nvar NAN = 0 / 0;\n\n/** Used to detect bad signed hexadecimal string values. */\nvar reIsBadHex = /^[-+]0x[0-9a-f]+$/i;\n\n/** Used to detect binary string values. */\nvar reIsBinary = /^0b[01]+$/i;\n\n/** Used to detect octal string values. */\nvar reIsOctal = /^0o[0-7]+$/i;\n\n/** Built-in method references without a dependency on `root`. */\nvar freeParseInt = parseInt;\n\n/**\n * Converts `value` to a number.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to process.\n * @returns {number} Returns the number.\n * @example\n *\n * _.toNumber(3.2);\n * // => 3.2\n *\n * _.toNumber(Number.MIN_VALUE);\n * // => 5e-324\n *\n * _.toNumber(Infinity);\n * // => Infinity\n *\n * _.toNumber('3.2');\n * // => 3.2\n */\nfunction toNumber(value) {\n if (typeof value == 'number') {\n return value;\n }\n if (isSymbol(value)) {\n return NAN;\n }\n if (isObject(value)) {\n var other = typeof value.valueOf == 'function' ? value.valueOf() : value;\n value = isObject(other) ? (other + '') : other;\n }\n if (typeof value != 'string') {\n return value === 0 ? value : +value;\n }\n value = baseTrim(value);\n var isBinary = reIsBinary.test(value);\n return (isBinary || reIsOctal.test(value))\n ? freeParseInt(value.slice(2), isBinary ? 2 : 8)\n : (reIsBadHex.test(value) ? NAN : +value);\n}\n\nmodule.exports = toNumber;\n","var baseDelay = require('./_baseDelay'),\n baseRest = require('./_baseRest'),\n toNumber = require('./toNumber');\n\n/**\n * Invokes `func` after `wait` milliseconds. Any additional arguments are\n * provided to `func` when it's invoked.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to delay.\n * @param {number} wait The number of milliseconds to delay invocation.\n * @param {...*} [args] The arguments to invoke `func` with.\n * @returns {number} Returns the timer id.\n * @example\n *\n * _.delay(function(text) {\n * console.log(text);\n * }, 1000, 'later');\n * // => Logs 'later' after one second.\n */\nvar delay = baseRest(function(func, wait, args) {\n return baseDelay(func, toNumber(wait) || 0, args);\n});\n\nmodule.exports = delay;\n","/*\n * Copyright 2021 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the 'License');\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an 'AS IS' BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n(function () {\n \"use strict\";\n\n const delay = require(\"lodash/delay\");\n\n const localStorage = window.localStorage;\n const htmlElement = document.documentElement;\n const prefersDarkColorScheme = window.matchMedia(\n \"(prefers-color-scheme: dark)\"\n );\n\n swithInitialTheme();\n window.addEventListener(\"load\", onWindowLoad);\n\n function swithInitialTheme() {\n if (isInitialThemeDark()) {\n htmlElement.classList.add(\"dark-theme\");\n }\n }\n\n function onWindowLoad() {\n const toggleCheckboxElement = document.querySelector(\n \"#switch-theme-checkbox\"\n );\n toggleCheckboxElement.checked = isInitialThemeDark();\n toggleCheckboxElement.addEventListener(\n \"change\",\n onThemeChange.bind(toggleCheckboxElement)\n );\n }\n\n function isInitialThemeDark() {\n const theme = loadTheme();\n return theme ? theme === \"dark\" : prefersDarkColorScheme.matches;\n }\n\n function onThemeChange() {\n if (this.checked) {\n delay(function () {\n htmlElement.classList.add(\"dark-theme\");\n }, 100);\n saveTheme(\"dark\");\n } else {\n delay(function () {\n htmlElement.classList.remove(\"dark-theme\");\n }, 100);\n saveTheme(\"light\");\n }\n }\n\n function saveTheme(theme) {\n if (localStorage) {\n localStorage.setItem(\"theme\", theme);\n }\n }\n\n function loadTheme() {\n return localStorage !== null ? localStorage.getItem(\"theme\") : null;\n }\n})();\n","\n}());"]} \ No newline at end of file diff --git a/docs/v4/js/site.js b/docs/v4/js/site.js new file mode 100644 index 0000000..24a40b4 --- /dev/null +++ b/docs/v4/js/site.js @@ -0,0 +1,7 @@ +!function(){"use strict";function n(){const n=document.getElementById("anchor-rewrite"),o=window.location.hash.substr(1);n&&o&&function(n,o){const e=[n];for(console.debug(n);o[n];){if(n=o[n],e.includes(n))return void console.error("Skipping circular anchor update");e.push(n)}window.location.hash=n}(o,JSON.parse(n.innerHTML))}window.addEventListener("load",n),window.addEventListener("hashchange",n)}(); +!function(){"use strict";!function(){let t=document.getElementById("author"),n=t;for(;t;)t.classList.contains("author")&&(n=t),t=t.nextElementSibling;n&&n.classList.add("last-author")}()}(); +!function(){var t=function(t,n,e){if("function"!=typeof t)throw new TypeError("Expected a function");return setTimeout((function(){t.apply(void 0,e)}),n)};var n=function(t){return t};var e=function(t,n,e){switch(e.length){case 0:return t.call(n);case 1:return t.call(n,e[0]);case 2:return t.call(n,e[0],e[1]);case 3:return t.call(n,e[0],e[1],e[2])}return t.apply(n,e)},r=Math.max;var o=function(t,n,o){return n=r(void 0===n?t.length-1:n,0),function(){for(var c=arguments,i=-1,u=r(c.length-n,0),a=Array(u);++i0){if(++n>=800)return arguments[0]}else n=0;return t.apply(void 0,arguments)}},G=D(I);var M=/\s/;var U=function(t){for(var n=t.length;n--&&M.test(t.charAt(n)););return n},z=/^\s+/;var B=function(t){return t?t.slice(0,U(t)+1).replace(z,""):t};var H=function(t){return null!=t&&"object"==typeof t};var J=function(t){return"symbol"==typeof t||H(t)&&"[object Symbol]"==g(t)},K=/^[-+]0x[0-9a-f]+$/i,Q=/^0b[01]+$/i,V=/^0o[0-7]+$/i,W=parseInt;var X=function(t){if("number"==typeof t)return t;if(J(t))return NaN;if(m(t)){var n="function"==typeof t.valueOf?t.valueOf():t;t=m(n)?n+"":n}if("string"!=typeof t)return 0===t?t:+t;t=B(t);var e=Q.test(t);return e||V.test(t)?W(t.slice(2),e?2:8):K.test(t)?NaN:+t},Y=function(t,e){return G(o(t,e,n),t+"")}((function(n,e,r){return t(n,X(e)||0,r)}));!function(){"use strict";function t(t){const e=t.querySelector("code").cloneNode(!0);for(const t of e.querySelectorAll(".hide-when-unfolded"))t.parentNode.removeChild(t);const r=e.innerText;r&&window.navigator.clipboard.writeText(r+"\n").then(n.bind(this))}function n(){this.classList.add("clicked")}function e(){this.classList.remove("clicked")}function r(t){const n=t.querySelector("code"),e=!n.classList.contains("unfolded");n.classList.remove(e?"folding":"unfolding"),n.classList.add(e?"unfolding":"folding"),Y((function(){n.classList.remove(e?"unfolding":"folding"),n.classList.toggle("unfolded")}),1100),o(this,!e)}function o(t,n){const e=n?"Expand folded text":"Collapse foldable text";t.classList.remove(n?"fold-button":"unfold-button"),t.classList.add(n?"unfold-button":"fold-button"),t.querySelector("span.label").innerText=e,t.title=e}!function(){for(const t of document.querySelectorAll(".doc pre.highlight")){const e=document.createElement("div");e.className="codetools",n(t,e)&&t.appendChild(e)}function n(n,i){let u=0;return function(t){return!!t.querySelector("span.hide-when-folded")}(n)&&(!function(t,n){const e=c();o(e,!0),e.addEventListener("click",r.bind(e,t)),n.appendChild(e)}(n,i),u++),window.navigator.clipboard&&(!function(n,r){const o=c("Copy to clipboard","copy-button");o.addEventListener("click",t.bind(o,n)),o.addEventListener("mouseleave",e.bind(o)),o.addEventListener("blur",e.bind(o));const i=document.createElement("span");o.appendChild(i),i.className="copied",r.appendChild(o)}(n,i),u++),u>0}function c(t,n){const e=document.createElement("button");e.className=n,e.title=t,e.type="button";const r=document.createElement("span");return r.appendChild(document.createTextNode(t)),r.className="label",e.appendChild(r),e}}()}()}(); +!function(){function e(n){return n instanceof Map?n.clear=n.delete=n.set=function(){throw new Error("map is read-only")}:n instanceof Set&&(n.add=n.clear=n.delete=function(){throw new Error("set is read-only")}),Object.freeze(n),Object.getOwnPropertyNames(n).forEach((function(t){var a=n[t];"object"!=typeof a||Object.isFrozen(a)||e(a)})),n}var n=e,t=e;n.default=t;class a{constructor(e){void 0===e.data&&(e.data={}),this.data=e.data,this.isMatchIgnored=!1}ignoreMatch(){this.isMatchIgnored=!0}}function i(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}function s(e,...n){const t=Object.create(null);for(const n in e)t[n]=e[n];return n.forEach((function(e){for(const n in e)t[n]=e[n]})),t}const r=e=>!!e.kind;class o{constructor(e,n){this.buffer="",this.classPrefix=n.classPrefix,e.walk(this)}addText(e){this.buffer+=i(e)}openNode(e){if(!r(e))return;let n=e.kind;e.sublanguage||(n=`${this.classPrefix}${n}`),this.span(n)}closeNode(e){r(e)&&(this.buffer+="")}value(){return this.buffer}span(e){this.buffer+=``}}class l{constructor(){this.rootNode={children:[]},this.stack=[this.rootNode]}get top(){return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){this.top.children.push(e)}openNode(e){const n={kind:e,children:[]};this.add(n),this.stack.push(n)}closeNode(){if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)}walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,n){return"string"==typeof n?e.addText(n):n.children&&(e.openNode(n),n.children.forEach((n=>this._walk(e,n))),e.closeNode(n)),e}static _collapse(e){"string"!=typeof e&&e.children&&(e.children.every((e=>"string"==typeof e))?e.children=[e.children.join("")]:e.children.forEach((e=>{l._collapse(e)})))}}class c extends l{constructor(e){super(),this.options=e}addKeyword(e,n){""!==e&&(this.openNode(n),this.addText(e),this.closeNode())}addText(e){""!==e&&this.add(e)}addSublanguage(e,n){const t=e.root;t.kind=n,t.sublanguage=!0,this.add(t)}toHTML(){return new o(this,this.options).value()}finalize(){return!0}}function g(e){return e?"string"==typeof e?e:e.source:null}const d=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;const u="[a-zA-Z]\\w*",b="[a-zA-Z_]\\w*",m="\\b\\d+(\\.\\d+)?",h="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",p="\\b(0b[01]+)",f={begin:"\\\\[\\s\\S]",relevance:0},_={className:"string",begin:"'",end:"'",illegal:"\\n",contains:[f]},E={className:"string",begin:'"',end:'"',illegal:"\\n",contains:[f]},v={begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},N=function(e,n,t={}){const a=s({className:"comment",begin:e,end:n,contains:[]},t);return a.contains.push(v),a.contains.push({className:"doctag",begin:"(?:TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):",relevance:0}),a},y=N("//","$"),w=N("/\\*","\\*/"),x=N("#","$"),M={className:"number",begin:m,relevance:0},O={className:"number",begin:h,relevance:0},k={className:"number",begin:p,relevance:0},R={className:"number",begin:m+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",relevance:0},S={begin:/(?=\/[^/\n]*\/)/,contains:[{className:"regexp",begin:/\//,end:/\/[gimuy]*/,illegal:/\n/,contains:[f,{begin:/\[/,end:/\]/,relevance:0,contains:[f]}]}]},A={className:"title",begin:u,relevance:0},T={className:"title",begin:b,relevance:0},C={begin:"\\.\\s*[a-zA-Z_]\\w*",relevance:0};var D=Object.freeze({__proto__:null,MATCH_NOTHING_RE:/\b\B/,IDENT_RE:u,UNDERSCORE_IDENT_RE:b,NUMBER_RE:m,C_NUMBER_RE:h,BINARY_NUMBER_RE:p,RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",SHEBANG:(e={})=>{const n=/^#![ ]*\//;return e.binary&&(e.begin=function(...e){return e.map((e=>g(e))).join("")}(n,/.*\b/,e.binary,/\b.*/)),s({className:"meta",begin:n,end:/$/,relevance:0,"on:begin":(e,n)=>{0!==e.index&&n.ignoreMatch()}},e)},BACKSLASH_ESCAPE:f,APOS_STRING_MODE:_,QUOTE_STRING_MODE:E,PHRASAL_WORDS_MODE:v,COMMENT:N,C_LINE_COMMENT_MODE:y,C_BLOCK_COMMENT_MODE:w,HASH_COMMENT_MODE:x,NUMBER_MODE:M,C_NUMBER_MODE:O,BINARY_NUMBER_MODE:k,CSS_NUMBER_MODE:R,REGEXP_MODE:S,TITLE_MODE:A,UNDERSCORE_TITLE_MODE:T,METHOD_GUARD:C,END_SAME_AS_BEGIN:function(e){return Object.assign(e,{"on:begin":(e,n)=>{n.data._beginMatch=e[1]},"on:end":(e,n)=>{n.data._beginMatch!==e[1]&&n.ignoreMatch()}})}});function L(e,n){"."===e.input[e.index-1]&&n.ignoreMatch()}function B(e,n){n&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)",e.__beforeBegin=L,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords,void 0===e.relevance&&(e.relevance=0))}function $(e,n){Array.isArray(e.illegal)&&(e.illegal=function(...e){return"("+e.map((e=>g(e))).join("|")+")"}(...e.illegal))}function I(e,n){if(e.match){if(e.begin||e.end)throw new Error("begin & end are not supported with match");e.begin=e.match,delete e.match}}function j(e,n){void 0===e.relevance&&(e.relevance=1)}const z=["of","and","for","in","not","or","if","then","parent","list","value"];function P(e,n,t="keyword"){const a={};return"string"==typeof e?i(t,e.split(" ")):Array.isArray(e)?i(t,e):Object.keys(e).forEach((function(t){Object.assign(a,P(e[t],n,t))})),a;function i(e,t){n&&(t=t.map((e=>e.toLowerCase()))),t.forEach((function(n){const t=n.split("|");a[t[0]]=[e,U(t[0],t[1])]}))}}function U(e,n){return n?Number(n):function(e){return z.includes(e.toLowerCase())}(e)?0:1}function K(e,{plugins:n}){function t(n,t){return new RegExp(g(n),"m"+(e.case_insensitive?"i":"")+(t?"g":""))}class a{constructor(){this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0}addRule(e,n){n.position=this.position++,this.matchIndexes[this.matchAt]=n,this.regexes.push([n,e]),this.matchAt+=function(e){return new RegExp(e.toString()+"|").exec("").length-1}(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null);const e=this.regexes.map((e=>e[1]));this.matcherRe=t(function(e,n="|"){let t=0;return e.map((e=>{t+=1;const n=t;let a=g(e),i="";for(;a.length>0;){const e=d.exec(a);if(!e){i+=a;break}i+=a.substring(0,e.index),a=a.substring(e.index+e[0].length),"\\"===e[0][0]&&e[1]?i+="\\"+String(Number(e[1])+n):(i+=e[0],"("===e[0]&&t++)}return i})).map((e=>`(${e})`)).join(n)}(e),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex;const n=this.matcherRe.exec(e);if(!n)return null;const t=n.findIndex(((e,n)=>n>0&&void 0!==e)),a=this.matchIndexes[t];return n.splice(0,t),Object.assign(n,a)}}class i{constructor(){this.rules=[],this.multiRegexes=[],this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){if(this.multiRegexes[e])return this.multiRegexes[e];const n=new a;return this.rules.slice(e).forEach((([e,t])=>n.addRule(e,t))),n.compile(),this.multiRegexes[e]=n,n}resumingScanAtSamePosition(){return 0!==this.regexIndex}considerAll(){this.regexIndex=0}addRule(e,n){this.rules.push([e,n]),"begin"===n.type&&this.count++}exec(e){const n=this.getMatcher(this.regexIndex);n.lastIndex=this.lastIndex;let t=n.exec(e);if(this.resumingScanAtSamePosition())if(t&&t.index===this.lastIndex);else{const n=this.getMatcher(0);n.lastIndex=this.lastIndex+1,t=n.exec(e)}return t&&(this.regexIndex+=t.position+1,this.regexIndex===this.count&&this.considerAll()),t}}if(e.compilerExtensions||(e.compilerExtensions=[]),e.contains&&e.contains.includes("self"))throw new Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.");return e.classNameAliases=s(e.classNameAliases||{}),function n(a,r){const o=a;if(a.isCompiled)return o;[I].forEach((e=>e(a,r))),e.compilerExtensions.forEach((e=>e(a,r))),a.__beforeBegin=null,[B,$,j].forEach((e=>e(a,r))),a.isCompiled=!0;let l=null;if("object"==typeof a.keywords&&(l=a.keywords.$pattern,delete a.keywords.$pattern),a.keywords&&(a.keywords=P(a.keywords,e.case_insensitive)),a.lexemes&&l)throw new Error("ERR: Prefer `keywords.$pattern` to `mode.lexemes`, BOTH are not allowed. (see mode reference) ");return l=l||a.lexemes||/\w+/,o.keywordPatternRe=t(l,!0),r&&(a.begin||(a.begin=/\B|\b/),o.beginRe=t(a.begin),a.endSameAsBegin&&(a.end=a.begin),a.end||a.endsWithParent||(a.end=/\B|\b/),a.end&&(o.endRe=t(a.end)),o.terminatorEnd=g(a.end)||"",a.endsWithParent&&r.terminatorEnd&&(o.terminatorEnd+=(a.end?"|":"")+r.terminatorEnd)),a.illegal&&(o.illegalRe=t(a.illegal)),a.contains||(a.contains=[]),a.contains=[].concat(...a.contains.map((function(e){return function(e){e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map((function(n){return s(e,{variants:null},n)})));if(e.cachedVariants)return e.cachedVariants;if(H(e))return s(e,{starts:e.starts?s(e.starts):null});if(Object.isFrozen(e))return s(e);return e}("self"===e?a:e)}))),a.contains.forEach((function(e){n(e,o)})),a.starts&&n(a.starts,r),o.matcher=function(e){const n=new i;return e.contains.forEach((e=>n.addRule(e.begin,{rule:e,type:"begin"}))),e.terminatorEnd&&n.addRule(e.terminatorEnd,{type:"end"}),e.illegal&&n.addRule(e.illegal,{type:"illegal"}),n}(o),o}(e)}function H(e){return!!e&&(e.endsWithParent||H(e.starts))}function Z(e){const n={props:["language","code","autodetect"],data:function(){return{detectedLanguage:"",unknownLanguage:!1}},computed:{className(){return this.unknownLanguage?"":"hljs "+this.detectedLanguage},highlighted(){if(!this.autoDetect&&!e.getLanguage(this.language))return console.warn(`The language "${this.language}" you specified could not be found.`),this.unknownLanguage=!0,i(this.code);let n={};return this.autoDetect?(n=e.highlightAuto(this.code),this.detectedLanguage=n.language):(n=e.highlight(this.language,this.code,this.ignoreIllegals),this.detectedLanguage=this.language),n.value},autoDetect(){return!this.language||(e=this.autodetect,Boolean(e||""===e));var e},ignoreIllegals:()=>!0},render(e){return e("pre",{},[e("code",{class:this.className,domProps:{innerHTML:this.highlighted}})])}};return{Component:n,VuePlugin:{install(e){e.component("highlightjs",n)}}}}const G={"after:highlightElement":({el:e,result:n,text:t})=>{const a=F(e);if(!a.length)return;const s=document.createElement("div");s.innerHTML=n.value,n.value=function(e,n,t){let a=0,s="";const r=[];function o(){return e.length&&n.length?e[0].offset!==n[0].offset?e[0].offset"}function c(e){s+=""}function g(e){("start"===e.event?l:c)(e.node)}for(;e.length||n.length;){let n=o();if(s+=i(t.substring(a,n[0].offset)),a=n[0].offset,n===e){r.reverse().forEach(c);do{g(n.splice(0,1)[0]),n=o()}while(n===e&&n.length&&n[0].offset===a);r.reverse().forEach(l)}else"start"===n[0].event?r.push(n[0].node):r.pop(),g(n.splice(0,1)[0])}return s+i(t.substr(a))}(a,F(s),t)}};function q(e){return e.nodeName.toLowerCase()}function F(e){const n=[];return function e(t,a){for(let i=t.firstChild;i;i=i.nextSibling)3===i.nodeType?a+=i.nodeValue.length:1===i.nodeType&&(n.push({event:"start",offset:a,node:i}),a=e(i,a),q(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:i}));return a}(e,0),n}const W={},Q=e=>{console.error(e)},X=(e,...n)=>{console.log(`WARN: ${e}`,...n)},V=(e,n)=>{W[`${e}/${n}`]||(console.log(`Deprecated as of ${e}. ${n}`),W[`${e}/${n}`]=!0)},J=i,Y=s,ee=Symbol("nomatch");var ne=function(e){const t=Object.create(null),i=Object.create(null),s=[];let r=!0;const o=/(^(<[^>]+>|\t|)+|\n)/gm,l="Could not find the language '{}', did you forget to load/include a language module?",g={disableAutodetect:!0,name:"Plain text",contains:[]};let d={noHighlightRe:/^(no-?highlight)$/i,languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:null,__emitter:c};function u(e){return d.noHighlightRe.test(e)}function b(e,n,t,a){let i="",s="";"object"==typeof n?(i=e,t=n.ignoreIllegals,s=n.language,a=void 0):(V("10.7.0","highlight(lang, code, ...args) has been deprecated."),V("10.7.0","Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277"),s=e,i=n);const r={code:i,language:s};O("before:highlight",r);const o=r.result?r.result:m(r.language,r.code,t,a);return o.code=r.code,O("after:highlight",o),o}function m(e,n,i,o){function c(e,n){const t=N.case_insensitive?n[0].toLowerCase():n[0];return Object.prototype.hasOwnProperty.call(e.keywords,t)&&e.keywords[t]}function g(){null!=M.subLanguage?function(){if(""===R)return;let e=null;if("string"==typeof M.subLanguage){if(!t[M.subLanguage])return void k.addText(R);e=m(M.subLanguage,R,!0,O[M.subLanguage]),O[M.subLanguage]=e.top}else e=h(R,M.subLanguage.length?M.subLanguage:null);M.relevance>0&&(S+=e.relevance),k.addSublanguage(e.emitter,e.language)}():function(){if(!M.keywords)return void k.addText(R);let e=0;M.keywordPatternRe.lastIndex=0;let n=M.keywordPatternRe.exec(R),t="";for(;n;){t+=R.substring(e,n.index);const a=c(M,n);if(a){const[e,i]=a;if(k.addText(t),t="",S+=i,e.startsWith("_"))t+=n[0];else{const t=N.classNameAliases[e]||e;k.addKeyword(n[0],t)}}else t+=n[0];e=M.keywordPatternRe.lastIndex,n=M.keywordPatternRe.exec(R)}t+=R.substr(e),k.addText(t)}(),R=""}function u(e){return e.className&&k.openNode(N.classNameAliases[e.className]||e.className),M=Object.create(e,{parent:{value:M}}),M}function b(e,n,t){let i=function(e,n){const t=e&&e.exec(n);return t&&0===t.index}(e.endRe,t);if(i){if(e["on:end"]){const t=new a(e);e["on:end"](n,t),t.isMatchIgnored&&(i=!1)}if(i){for(;e.endsParent&&e.parent;)e=e.parent;return e}}if(e.endsWithParent)return b(e.parent,n,t)}function p(e){return 0===M.matcher.regexIndex?(R+=e[0],1):(C=!0,0)}function f(e){const n=e[0],t=e.rule,i=new a(t),s=[t.__beforeBegin,t["on:begin"]];for(const t of s)if(t&&(t(e,i),i.isMatchIgnored))return p(n);return t&&t.endSameAsBegin&&(t.endRe=new RegExp(n.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"),"m")),t.skip?R+=n:(t.excludeBegin&&(R+=n),g(),t.returnBegin||t.excludeBegin||(R=n)),u(t),t.returnBegin?0:n.length}function _(e){const t=e[0],a=n.substr(e.index),i=b(M,e,a);if(!i)return ee;const s=M;s.skip?R+=t:(s.returnEnd||s.excludeEnd||(R+=t),g(),s.excludeEnd&&(R=t));do{M.className&&k.closeNode(),M.skip||M.subLanguage||(S+=M.relevance),M=M.parent}while(M!==i.parent);return i.starts&&(i.endSameAsBegin&&(i.starts.endRe=i.endRe),u(i.starts)),s.returnEnd?0:t.length}let E={};function v(t,a){const s=a&&a[0];if(R+=t,null==s)return g(),0;if("begin"===E.type&&"end"===a.type&&E.index===a.index&&""===s){if(R+=n.slice(a.index,a.index+1),!r){const n=new Error("0 width match regex");throw n.languageName=e,n.badRule=E.rule,n}return 1}if(E=a,"begin"===a.type)return f(a);if("illegal"===a.type&&!i){const e=new Error('Illegal lexeme "'+s+'" for mode "'+(M.className||"")+'"');throw e.mode=M,e}if("end"===a.type){const e=_(a);if(e!==ee)return e}if("illegal"===a.type&&""===s)return 1;if(T>1e5&&T>3*a.index){throw new Error("potential infinite loop, way more iterations than matches")}return R+=s,s.length}const N=w(e);if(!N)throw Q(l.replace("{}",e)),new Error('Unknown language: "'+e+'"');const y=K(N,{plugins:s});let x="",M=o||y;const O={},k=new d.__emitter(d);!function(){const e=[];for(let n=M;n!==N;n=n.parent)n.className&&e.unshift(n.className);e.forEach((e=>k.openNode(e)))}();let R="",S=0,A=0,T=0,C=!1;try{for(M.matcher.considerAll();;){T++,C?C=!1:M.matcher.considerAll(),M.matcher.lastIndex=A;const e=M.matcher.exec(n);if(!e)break;const t=v(n.substring(A,e.index),e);A=e.index+t}return v(n.substr(A)),k.closeAllNodes(),k.finalize(),x=k.toHTML(),{relevance:Math.floor(S),value:x,language:e,illegal:!1,emitter:k,top:M}}catch(t){if(t.message&&t.message.includes("Illegal"))return{illegal:!0,illegalBy:{msg:t.message,context:n.slice(A-100,A+100),mode:t.mode},sofar:x,relevance:0,value:J(n),emitter:k};if(r)return{illegal:!1,relevance:0,value:J(n),emitter:k,language:e,top:M,errorRaised:t};throw t}}function h(e,n){n=n||d.languages||Object.keys(t);const a=function(e){const n={relevance:0,emitter:new d.__emitter(d),value:J(e),illegal:!1,top:g};return n.emitter.addText(e),n}(e),i=n.filter(w).filter(M).map((n=>m(n,e,!1)));i.unshift(a);const s=i.sort(((e,n)=>{if(e.relevance!==n.relevance)return n.relevance-e.relevance;if(e.language&&n.language){if(w(e.language).supersetOf===n.language)return 1;if(w(n.language).supersetOf===e.language)return-1}return 0})),[r,o]=s,l=r;return l.second_best=o,l}const p={"before:highlightElement":({el:e})=>{d.useBR&&(e.innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n"))},"after:highlightElement":({result:e})=>{d.useBR&&(e.value=e.value.replace(/\n/g,"
      "))}},f=/^(<[^>]+>|\t)+/gm,_={"after:highlightElement":({result:e})=>{d.tabReplace&&(e.value=e.value.replace(f,(e=>e.replace(/\t/g,d.tabReplace))))}};function E(e){let n=null;const t=function(e){let n=e.className+" ";n+=e.parentNode?e.parentNode.className:"";const t=d.languageDetectRe.exec(n);if(t){const n=w(t[1]);return n||(X(l.replace("{}",t[1])),X("Falling back to no-highlight mode for this block.",e)),n?t[1]:"no-highlight"}return n.split(/\s+/).find((e=>u(e)||w(e)))}(e);if(u(t))return;O("before:highlightElement",{el:e,language:t}),n=e;const a=n.textContent,s=t?b(a,{language:t,ignoreIllegals:!0}):h(a);O("after:highlightElement",{el:e,result:s,text:a}),e.innerHTML=s.value,function(e,n,t){const a=n?i[n]:t;e.classList.add("hljs"),a&&e.classList.add(a)}(e,t,s.language),e.result={language:s.language,re:s.relevance,relavance:s.relevance},s.second_best&&(e.second_best={language:s.second_best.language,re:s.second_best.relevance,relavance:s.second_best.relevance})}const v=()=>{if(v.called)return;v.called=!0,V("10.6.0","initHighlighting() is deprecated. Use highlightAll() instead.");document.querySelectorAll("pre code").forEach(E)};let N=!1;function y(){if("loading"===document.readyState)return void(N=!0);document.querySelectorAll("pre code").forEach(E)}function w(e){return e=(e||"").toLowerCase(),t[e]||t[i[e]]}function x(e,{languageName:n}){"string"==typeof e&&(e=[e]),e.forEach((e=>{i[e.toLowerCase()]=n}))}function M(e){const n=w(e);return n&&!n.disableAutodetect}function O(e,n){const t=e;s.forEach((function(e){e[t]&&e[t](n)}))}"undefined"!=typeof window&&window.addEventListener&&window.addEventListener("DOMContentLoaded",(function(){N&&y()}),!1),Object.assign(e,{highlight:b,highlightAuto:h,highlightAll:y,fixMarkup:function(e){return V("10.2.0","fixMarkup will be removed entirely in v11.0"),V("10.2.0","Please see https://github.com/highlightjs/highlight.js/issues/2534"),n=e,d.tabReplace||d.useBR?n.replace(o,(e=>"\n"===e?d.useBR?"
      ":e:d.tabReplace?e.replace(/\t/g,d.tabReplace):e)):n;var n},highlightElement:E,highlightBlock:function(e){return V("10.7.0","highlightBlock will be removed entirely in v12.0"),V("10.7.0","Please use highlightElement now."),E(e)},configure:function(e){e.useBR&&(V("10.3.0","'useBR' will be removed entirely in v11.0"),V("10.3.0","Please see https://github.com/highlightjs/highlight.js/issues/2559")),d=Y(d,e)},initHighlighting:v,initHighlightingOnLoad:function(){V("10.6.0","initHighlightingOnLoad() is deprecated. Use highlightAll() instead."),N=!0},registerLanguage:function(n,a){let i=null;try{i=a(e)}catch(e){if(Q("Language definition for '{}' could not be registered.".replace("{}",n)),!r)throw e;Q(e),i=g}i.name||(i.name=n),t[n]=i,i.rawDefinition=a.bind(null,e),i.aliases&&x(i.aliases,{languageName:n})},unregisterLanguage:function(e){delete t[e];for(const n of Object.keys(i))i[n]===e&&delete i[n]},listLanguages:function(){return Object.keys(t)},getLanguage:w,registerAliases:x,requireLanguage:function(e){V("10.4.0","requireLanguage will be removed entirely in v11."),V("10.4.0","Please see https://github.com/highlightjs/highlight.js/pull/2844");const n=w(e);if(n)return n;throw new Error("The '{}' language is required, but not loaded.".replace("{}",e))},autoDetection:M,inherit:Y,addPlugin:function(e){!function(e){e["before:highlightBlock"]&&!e["before:highlightElement"]&&(e["before:highlightElement"]=n=>{e["before:highlightBlock"](Object.assign({block:n.el},n))}),e["after:highlightBlock"]&&!e["after:highlightElement"]&&(e["after:highlightElement"]=n=>{e["after:highlightBlock"](Object.assign({block:n.el},n))})}(e),s.push(e)},vuePlugin:Z(e).VuePlugin}),e.debugMode=function(){r=!1},e.safeMode=function(){r=!0},e.versionString="10.7.3";for(const e in D)"object"==typeof D[e]&&n(D[e]);return Object.assign(e,D),e.addPlugin(p),e.addPlugin(G),e.addPlugin(_),e}({});function te(...e){return e.map((e=>{return(n=e)?"string"==typeof n?n:n.source:null;var n})).join("")}var ae=function(e){const n=[{className:"strong",begin:/\*{2}([^\n]+?)\*{2}/},{className:"strong",begin:te(/\*\*/,/((\*(?!\*)|\\[^\n]|[^*\n\\])+\n)+/,/(\*(?!\*)|\\[^\n]|[^*\n\\])*/,/\*\*/),relevance:0},{className:"strong",begin:/\B\*(\S|\S[^\n]*?\S)\*(?!\w)/},{className:"strong",begin:/\*[^\s]([^\n]+\n)+([^\n]+)\*/}],t=[{className:"emphasis",begin:/_{2}([^\n]+?)_{2}/},{className:"emphasis",begin:te(/__/,/((_(?!_)|\\[^\n]|[^_\n\\])+\n)+/,/(_(?!_)|\\[^\n]|[^_\n\\])*/,/__/),relevance:0},{className:"emphasis",begin:/\b_(\S|\S[^\n]*?\S)_(?!\w)/},{className:"emphasis",begin:/_[^\s]([^\n]+\n)+([^\n]+)_/},{className:"emphasis",begin:"\\B'(?!['\\s])",end:"(\\n{2}|')",contains:[{begin:"\\\\'\\w",relevance:0}],relevance:0}];return{name:"AsciiDoc",aliases:["adoc"],contains:[e.COMMENT("^/{4,}\\n","\\n/{4,}$",{relevance:10}),e.COMMENT("^//","$",{relevance:0}),{className:"title",begin:"^\\.\\w.*$"},{begin:"^[=\\*]{4,}\\n",end:"\\n^[=\\*]{4,}$",relevance:10},{className:"section",relevance:10,variants:[{begin:"^(={1,6})[ \t].+?([ \t]\\1)?$"},{begin:"^[^\\[\\]\\n]+?\\n[=\\-~\\^\\+]{2,}$"}]},{className:"meta",begin:"^:.+?:",end:"\\s",excludeEnd:!0,relevance:10},{className:"meta",begin:"^\\[.+?\\]$",relevance:0},{className:"quote",begin:"^_{4,}\\n",end:"\\n_{4,}$",relevance:10},{className:"code",begin:"^[\\-\\.]{4,}\\n",end:"\\n[\\-\\.]{4,}$",relevance:10},{begin:"^\\+{4,}\\n",end:"\\n\\+{4,}$",contains:[{begin:"<",end:">",subLanguage:"xml",relevance:0}],relevance:10},{className:"bullet",begin:"^(\\*+|-+|\\.+|[^\\n]+?::)\\s+"},{className:"symbol",begin:"^(NOTE|TIP|IMPORTANT|WARNING|CAUTION):\\s+",relevance:10},{begin:/\\[*_`]/},{begin:/\\\\\*{2}[^\n]*?\*{2}/},{begin:/\\\\_{2}[^\n]*_{2}/},{begin:/\\\\`{2}[^\n]*`{2}/},{begin:/[:;}][*_`](?![*_`])/},...n,...t,{className:"string",variants:[{begin:"``.+?''"},{begin:"`.+?'"}]},{className:"code",begin:/`{2}/,end:/(\n{2}|`{2})/},{className:"code",begin:"(`.+?`|\\+.+?\\+)",relevance:0},{className:"code",begin:"^[ \\t]",end:"$",relevance:0},{begin:"^'{3,}[ \\t]*$",relevance:10},{begin:"(link:)?(http|https|ftp|file|irc|image:?):\\S+?\\[[^[]*?\\]",returnBegin:!0,contains:[{begin:"(link|image:?):",relevance:0},{className:"link",begin:"\\w",end:"[^\\[]+",relevance:0},{className:"string",begin:"\\[",end:"\\]",excludeBegin:!0,excludeEnd:!0,relevance:0}],relevance:10}]}};function ie(...e){return e.map((e=>{return(n=e)?"string"==typeof n?n:n.source:null;var n})).join("")}var se=function(e){const n={},t={begin:/\$\{/,end:/\}/,contains:["self",{begin:/:-/,contains:[n]}]};Object.assign(n,{className:"variable",variants:[{begin:ie(/\$[\w\d#@][\w\d_]*/,"(?![\\w\\d])(?![$])")},t]});const a={className:"subst",begin:/\$\(/,end:/\)/,contains:[e.BACKSLASH_ESCAPE]},i={begin:/<<-?\s*(?=\w+)/,starts:{contains:[e.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/,className:"string"})]}},s={className:"string",begin:/"/,end:/"/,contains:[e.BACKSLASH_ESCAPE,n,a]};a.contains.push(s);const r={begin:/\$\(\(/,end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},e.NUMBER_MODE,n]},o=e.SHEBANG({binary:`(${["fish","bash","zsh","sh","csh","ksh","tcsh","dash","scsh"].join("|")})`,relevance:10}),l={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0,contains:[e.inherit(e.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{name:"Bash",aliases:["sh","zsh"],keywords:{$pattern:/\b[a-z._-]+\b/,keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp"},contains:[o,e.SHEBANG(),l,r,e.HASH_COMMENT_MODE,i,s,{className:"",begin:/\\"/},{className:"string",begin:/'/,end:/'/},n]}};const re=["a","abbr","address","article","aside","audio","b","blockquote","body","button","canvas","caption","cite","code","dd","del","details","dfn","div","dl","dt","em","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","html","i","iframe","img","input","ins","kbd","label","legend","li","main","mark","menu","nav","object","ol","p","q","quote","samp","section","span","strong","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","tr","ul","var","video"],oe=["any-hover","any-pointer","aspect-ratio","color","color-gamut","color-index","device-aspect-ratio","device-height","device-width","display-mode","forced-colors","grid","height","hover","inverted-colors","monochrome","orientation","overflow-block","overflow-inline","pointer","prefers-color-scheme","prefers-contrast","prefers-reduced-motion","prefers-reduced-transparency","resolution","scan","scripting","update","width","min-width","max-width","min-height","max-height"],le=["active","any-link","blank","checked","current","default","defined","dir","disabled","drop","empty","enabled","first","first-child","first-of-type","fullscreen","future","focus","focus-visible","focus-within","has","host","host-context","hover","indeterminate","in-range","invalid","is","lang","last-child","last-of-type","left","link","local-link","not","nth-child","nth-col","nth-last-child","nth-last-col","nth-last-of-type","nth-of-type","only-child","only-of-type","optional","out-of-range","past","placeholder-shown","read-only","read-write","required","right","root","scope","target","target-within","user-invalid","valid","visited","where"],ce=["after","backdrop","before","cue","cue-region","first-letter","first-line","grammar-error","marker","part","placeholder","selection","slotted","spelling-error"],ge=["align-content","align-items","align-self","animation","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-timing-function","auto","backface-visibility","background","background-attachment","background-clip","background-color","background-image","background-origin","background-position","background-repeat","background-size","border","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-decoration-break","box-shadow","box-sizing","break-after","break-before","break-inside","caption-side","clear","clip","clip-path","color","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","content","counter-increment","counter-reset","cursor","direction","display","empty-cells","filter","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","font","font-display","font-family","font-feature-settings","font-kerning","font-language-override","font-size","font-size-adjust","font-smoothing","font-stretch","font-style","font-variant","font-variant-ligatures","font-variation-settings","font-weight","height","hyphens","icon","image-orientation","image-rendering","image-resolution","ime-mode","inherit","initial","justify-content","left","letter-spacing","line-height","list-style","list-style-image","list-style-position","list-style-type","margin","margin-bottom","margin-left","margin-right","margin-top","marks","mask","max-height","max-width","min-height","min-width","nav-down","nav-index","nav-left","nav-right","nav-up","none","normal","object-fit","object-position","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-wrap","overflow-x","overflow-y","padding","padding-bottom","padding-left","padding-right","padding-top","page-break-after","page-break-before","page-break-inside","perspective","perspective-origin","pointer-events","position","quotes","resize","right","src","tab-size","table-layout","text-align","text-align-last","text-decoration","text-decoration-color","text-decoration-line","text-decoration-style","text-indent","text-overflow","text-rendering","text-shadow","text-transform","text-underline-position","top","transform","transform-origin","transform-style","transition","transition-delay","transition-duration","transition-property","transition-timing-function","unicode-bidi","vertical-align","visibility","white-space","widows","width","word-break","word-spacing","word-wrap","z-index"].reverse();function de(e){return function(...e){return e.map((e=>function(e){return e?"string"==typeof e?e:e.source:null}(e))).join("")}("(?=",e,")")}var ue=function(e){const n=(e=>({IMPORTANT:{className:"meta",begin:"!important"},HEXCOLOR:{className:"number",begin:"#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})"},ATTRIBUTE_SELECTOR_MODE:{className:"selector-attr",begin:/\[/,end:/\]/,illegal:"$",contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]}}))(e),t=[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE];return{name:"CSS",case_insensitive:!0,illegal:/[=|'\$]/,keywords:{keyframePosition:"from to"},classNameAliases:{keyframePosition:"selector-tag"},contains:[e.C_BLOCK_COMMENT_MODE,{begin:/-(webkit|moz|ms|o)-(?=[a-z])/},e.CSS_NUMBER_MODE,{className:"selector-id",begin:/#[A-Za-z0-9_-]+/,relevance:0},{className:"selector-class",begin:"\\.[a-zA-Z-][a-zA-Z0-9_-]*",relevance:0},n.ATTRIBUTE_SELECTOR_MODE,{className:"selector-pseudo",variants:[{begin:":("+le.join("|")+")"},{begin:"::("+ce.join("|")+")"}]},{className:"attribute",begin:"\\b("+ge.join("|")+")\\b"},{begin:":",end:"[;}]",contains:[n.HEXCOLOR,n.IMPORTANT,e.CSS_NUMBER_MODE,...t,{begin:/(url|data-uri)\(/,end:/\)/,relevance:0,keywords:{built_in:"url data-uri"},contains:[{className:"string",begin:/[^)]/,endsWithParent:!0,excludeEnd:!0}]},{className:"built_in",begin:/[\w-]+(?=\()/}]},{begin:de(/@/),end:"[{;]",relevance:0,illegal:/:/,contains:[{className:"keyword",begin:/@-?\w[\w]*(-\w+)*/},{begin:/\s/,endsWithParent:!0,excludeEnd:!0,relevance:0,keywords:{$pattern:/[a-z-]+/,keyword:"and or not only",attribute:oe.join(" ")},contains:[{begin:/[a-z-]+(?=:)/,className:"attribute"},...t,e.CSS_NUMBER_MODE]}]},{className:"selector-tag",begin:"\\b("+re.join("|")+")\\b"}]}};var be=function(e){return{name:"Diff",aliases:["patch"],contains:[{className:"meta",relevance:10,variants:[{begin:/^@@ +-\d+,\d+ +\+\d+,\d+ +@@/},{begin:/^\*\*\* +\d+,\d+ +\*\*\*\*$/},{begin:/^--- +\d+,\d+ +----$/}]},{className:"comment",variants:[{begin:/Index: /,end:/$/},{begin:/^index/,end:/$/},{begin:/={3,}/,end:/$/},{begin:/^-{3}/,end:/$/},{begin:/^\*{3} /,end:/$/},{begin:/^\+{3}/,end:/$/},{begin:/^\*{15}$/},{begin:/^diff --git/,end:/$/}]},{className:"addition",begin:/^\+/,end:/$/},{className:"deletion",begin:/^-/,end:/$/},{className:"addition",begin:/^!/,end:/$/}]}};var me=function(e){return{name:"Dockerfile",aliases:["docker"],case_insensitive:!0,keywords:"from maintainer expose env arg user onbuild stopsignal",contains:[e.HASH_COMMENT_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.NUMBER_MODE,{beginKeywords:"run cmd entrypoint volume add copy workdir label healthcheck shell",starts:{end:/[^\\]$/,subLanguage:"bash"}}],illegal:"function(e){return e?"string"==typeof e?e:e.source:null}(e))).join("")}("(?=",e,")")}function _e(e,n={}){return n.variants=e,n}var Ee=function(e){const n="[A-Za-z0-9_$]+",t=_e([e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{begin:/\w+@/,relevance:0},{className:"doctag",begin:"@[A-Za-z]+"}]})]),a={className:"regexp",begin:/~?\/[^\/\n]+\//,contains:[e.BACKSLASH_ESCAPE]},i=_e([e.BINARY_NUMBER_MODE,e.C_NUMBER_MODE]),s=_e([{begin:/"""/,end:/"""/},{begin:/'''/,end:/'''/},{begin:"\\$/",end:"/\\$",relevance:10},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE],{className:"string"});return{name:"Groovy",keywords:{built_in:"this super",literal:"true false null",keyword:"byte short char int long boolean float double void def as in assert trait abstract static volatile transient public private protected synchronized final class interface enum if else for while switch case break default continue throw throws try catch finally implements extends new import package return instanceof"},contains:[e.SHEBANG({binary:"groovy",relevance:10}),t,s,a,i,{className:"class",beginKeywords:"class interface trait enum",end:/\{/,illegal:":",contains:[{beginKeywords:"extends implements"},e.UNDERSCORE_TITLE_MODE]},{className:"meta",begin:"@[A-Za-z]+",relevance:0},{className:"attr",begin:n+"[ \t]*:",relevance:0},{begin:/\?/,end:/:/,relevance:0,contains:[t,s,a,i,"self"]},{className:"symbol",begin:"^[ \t]*"+fe(n+":"),excludeBegin:!0,end:n+":",relevance:0}],illegal:/#|<\//}};function ve(...e){return e.map((e=>{return(n=e)?"string"==typeof n?n:n.source:null;var n})).join("")}var Ne=function(e){const n="HTTP/(2|1\\.[01])",t={className:"attribute",begin:ve("^",/[A-Za-z][A-Za-z0-9-]*/,"(?=\\:\\s)"),starts:{contains:[{className:"punctuation",begin:/: /,relevance:0,starts:{end:"$",relevance:0}}]}},a=[t,{begin:"\\n\\n",starts:{subLanguage:[],endsWithParent:!0}}];return{name:"HTTP",aliases:["https"],illegal:/\S/,contains:[{begin:"^(?="+n+" \\d{3})",end:/$/,contains:[{className:"meta",begin:n},{className:"number",begin:"\\b\\d{3}\\b"}],starts:{end:/\b\B/,illegal:/\S/,contains:a}},{begin:"(?=^[A-Z]+ (.*?) "+n+"$)",end:/$/,contains:[{className:"string",begin:" ",end:" ",excludeBegin:!0,excludeEnd:!0},{className:"meta",begin:n},{className:"keyword",begin:"[A-Z]+"}],starts:{end:/\b\B/,illegal:/\S/,contains:a}},e.inherit(t,{relevance:0})]}},ye="\\.([0-9](_*[0-9])*)",we="[0-9a-fA-F](_*[0-9a-fA-F])*",xe={className:"number",variants:[{begin:`(\\b([0-9](_*[0-9])*)((${ye})|\\.)?|(${ye}))[eE][+-]?([0-9](_*[0-9])*)[fFdD]?\\b`},{begin:`\\b([0-9](_*[0-9])*)((${ye})[fFdD]?\\b|\\.([fFdD]\\b)?)`},{begin:`(${ye})[fFdD]?\\b`},{begin:"\\b([0-9](_*[0-9])*)[fFdD]\\b"},{begin:`\\b0[xX]((${we})\\.?|(${we})?\\.(${we}))[pP][+-]?([0-9](_*[0-9])*)[fFdD]?\\b`},{begin:"\\b(0|[1-9](_*[0-9])*)[lL]?\\b"},{begin:`\\b0[xX](${we})[lL]?\\b`},{begin:"\\b0(_*[0-7])*[lL]?\\b"},{begin:"\\b0[bB][01](_*[01])*[lL]?\\b"}],relevance:0};var Me=function(e){var n="[À-ʸa-zA-Z_$][À-ʸa-zA-Z_$0-9]*",t="false synchronized int abstract float private char boolean var static null if const for true while long strictfp finally protected import native final void enum else break transient catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private module requires exports do",a={className:"meta",begin:"@"+n,contains:[{begin:/\(/,end:/\)/,contains:["self"]}]};const i=xe;return{name:"Java",aliases:["jsp"],keywords:t,illegal:/<\/|#/,contains:[e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{begin:/\w+@/,relevance:0},{className:"doctag",begin:"@[A-Za-z]+"}]}),{begin:/import java\.[a-z]+\./,keywords:"import",relevance:2},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{className:"class",beginKeywords:"class interface enum",end:/[{;=]/,excludeEnd:!0,relevance:1,keywords:"class interface enum",illegal:/[:"\[\]]/,contains:[{beginKeywords:"extends implements"},e.UNDERSCORE_TITLE_MODE]},{beginKeywords:"new throw return else",relevance:0},{className:"class",begin:"record\\s+"+e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,excludeEnd:!0,end:/[{;=]/,keywords:t,contains:[{beginKeywords:"record"},{begin:e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,relevance:0,contains:[e.UNDERSCORE_TITLE_MODE]},{className:"params",begin:/\(/,end:/\)/,keywords:t,relevance:0,contains:[e.C_BLOCK_COMMENT_MODE]},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:"function",begin:"([À-ʸa-zA-Z_$][À-ʸa-zA-Z_$0-9]*(<[À-ʸa-zA-Z_$][À-ʸa-zA-Z_$0-9]*(\\s*,\\s*[À-ʸa-zA-Z_$][À-ʸa-zA-Z_$0-9]*)*>)?\\s+)+"+e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:t,contains:[{begin:e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,relevance:0,contains:[e.UNDERSCORE_TITLE_MODE]},{className:"params",begin:/\(/,end:/\)/,keywords:t,relevance:0,contains:[a,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,i,e.C_BLOCK_COMMENT_MODE]},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},i,a]}};const Oe="[A-Za-z$_][0-9A-Za-z$_]*",ke=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],Re=["true","false","null","undefined","NaN","Infinity"],Se=[].concat(["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],["arguments","this","super","console","window","document","localStorage","module","global"],["Intl","DataView","Number","Math","Date","String","RegExp","Object","Function","Boolean","Error","Symbol","Set","Map","WeakSet","WeakMap","Proxy","Reflect","JSON","Promise","Float64Array","Int16Array","Int32Array","Int8Array","Uint16Array","Uint32Array","Float32Array","Array","Uint8Array","Uint8ClampedArray","ArrayBuffer","BigInt64Array","BigUint64Array","BigInt"],["EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"]);function Ae(e){return Te("(?=",e,")")}function Te(...e){return e.map((e=>{return(n=e)?"string"==typeof n?n:n.source:null;var n})).join("")}var Ce=function(e){const n=Oe,t="<>",a="",i={begin:/<[A-Za-z0-9\\._:-]+/,end:/\/[A-Za-z0-9\\._:-]+>|\/>/,isTrulyOpeningTag:(e,n)=>{const t=e[0].length+e.index,a=e.input[t];"<"!==a?">"===a&&(((e,{after:n})=>{const t="",returnBegin:!0,end:"\\s*=>",contains:[{className:"params",variants:[{begin:e.UNDERSCORE_IDENT_RE,relevance:0},{className:null,begin:/\(\s*\)/,skip:!0},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:s,contains:p}]}]},{begin:/,/,relevance:0},{className:"",begin:/\s/,end:/\s*/,skip:!0},{variants:[{begin:t,end:a},{begin:i.begin,"on:begin":i.isTrulyOpeningTag,end:i.end}],subLanguage:"xml",contains:[{begin:i.begin,end:i.end,skip:!0,contains:["self"]}]}],relevance:0},{className:"function",beginKeywords:"function",end:/[{;]/,excludeEnd:!0,keywords:s,contains:["self",e.inherit(e.TITLE_MODE,{begin:n}),f],illegal:/%/},{beginKeywords:"while if switch catch for"},{className:"function",begin:e.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{",returnBegin:!0,contains:[f,e.inherit(e.TITLE_MODE,{begin:n})]},{variants:[{begin:"\\."+n},{begin:"\\$"+n}],relevance:0},{className:"class",beginKeywords:"class",end:/[{;=]/,excludeEnd:!0,illegal:/[:"[\]]/,contains:[{beginKeywords:"extends"},e.UNDERSCORE_TITLE_MODE]},{begin:/\b(?=constructor)/,end:/[{;]/,excludeEnd:!0,contains:[e.inherit(e.TITLE_MODE,{begin:n}),"self",f]},{begin:"(get|set)\\s+(?="+n+"\\()",end:/\{/,keywords:"get set",contains:[e.inherit(e.TITLE_MODE,{begin:n}),{begin:/\(\)/},f]},{begin:/\$[(.]/}]}};var De=function(e){const n={literal:"true false null"},t=[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE],a=[e.QUOTE_STRING_MODE,e.C_NUMBER_MODE],i={end:",",endsWithParent:!0,excludeEnd:!0,contains:a,keywords:n},s={begin:/\{/,end:/\}/,contains:[{className:"attr",begin:/"/,end:/"/,contains:[e.BACKSLASH_ESCAPE],illegal:"\\n"},e.inherit(i,{begin:/:/})].concat(t),illegal:"\\S"},r={begin:"\\[",end:"\\]",contains:[e.inherit(i)],illegal:"\\S"};return a.push(s,r),t.forEach((function(e){a.push(e)})),{name:"JSON",contains:a,keywords:n,illegal:"\\S"}},Le="\\.([0-9](_*[0-9])*)",Be="[0-9a-fA-F](_*[0-9a-fA-F])*",$e={className:"number",variants:[{begin:`(\\b([0-9](_*[0-9])*)((${Le})|\\.)?|(${Le}))[eE][+-]?([0-9](_*[0-9])*)[fFdD]?\\b`},{begin:`\\b([0-9](_*[0-9])*)((${Le})[fFdD]?\\b|\\.([fFdD]\\b)?)`},{begin:`(${Le})[fFdD]?\\b`},{begin:"\\b([0-9](_*[0-9])*)[fFdD]\\b"},{begin:`\\b0[xX]((${Be})\\.?|(${Be})?\\.(${Be}))[pP][+-]?([0-9](_*[0-9])*)[fFdD]?\\b`},{begin:"\\b(0|[1-9](_*[0-9])*)[lL]?\\b"},{begin:`\\b0[xX](${Be})[lL]?\\b`},{begin:"\\b0(_*[0-7])*[lL]?\\b"},{begin:"\\b0[bB][01](_*[01])*[lL]?\\b"}],relevance:0};var Ie=function(e){const n={keyword:"abstract as val var vararg get set class object open private protected public noinline crossinline dynamic final enum if else do while for when throw try catch finally import package is in fun override companion reified inline lateinit init interface annotation data sealed internal infix operator out by constructor super tailrec where const inner suspend typealias external expect actual",built_in:"Byte Short Char Int Long Boolean Float Double Void Unit Nothing",literal:"true false null"},t={className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"@"},a={className:"subst",begin:/\$\{/,end:/\}/,contains:[e.C_NUMBER_MODE]},i={className:"variable",begin:"\\$"+e.UNDERSCORE_IDENT_RE},s={className:"string",variants:[{begin:'"""',end:'"""(?=[^"])',contains:[i,a]},{begin:"'",end:"'",illegal:/\n/,contains:[e.BACKSLASH_ESCAPE]},{begin:'"',end:'"',illegal:/\n/,contains:[e.BACKSLASH_ESCAPE,i,a]}]};a.contains.push(s);const r={className:"meta",begin:"@(?:file|property|field|get|set|receiver|param|setparam|delegate)\\s*:(?:\\s*"+e.UNDERSCORE_IDENT_RE+")?"},o={className:"meta",begin:"@"+e.UNDERSCORE_IDENT_RE,contains:[{begin:/\(/,end:/\)/,contains:[e.inherit(s,{className:"meta-string"})]}]},l=$e,c=e.COMMENT("/\\*","\\*/",{contains:[e.C_BLOCK_COMMENT_MODE]}),g={variants:[{className:"type",begin:e.UNDERSCORE_IDENT_RE},{begin:/\(/,end:/\)/,contains:[]}]},d=g;return d.variants[1].contains=[g],g.variants[1].contains=[d],{name:"Kotlin",aliases:["kt","kts"],keywords:n,contains:[e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{className:"doctag",begin:"@[A-Za-z]+"}]}),e.C_LINE_COMMENT_MODE,c,{className:"keyword",begin:/\b(break|continue|return|this)\b/,starts:{contains:[{className:"symbol",begin:/@\w+/}]}},t,r,o,{className:"function",beginKeywords:"fun",end:"[(]|$",returnBegin:!0,excludeEnd:!0,keywords:n,relevance:5,contains:[{begin:e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,relevance:0,contains:[e.UNDERSCORE_TITLE_MODE]},{className:"type",begin://,keywords:"reified",relevance:0},{className:"params",begin:/\(/,end:/\)/,endsParent:!0,keywords:n,relevance:0,contains:[{begin:/:/,end:/[=,\/]/,endsWithParent:!0,contains:[g,e.C_LINE_COMMENT_MODE,c],relevance:0},e.C_LINE_COMMENT_MODE,c,r,o,s,e.C_NUMBER_MODE]},c]},{className:"class",beginKeywords:"class interface trait",end:/[:\{(]|$/,excludeEnd:!0,illegal:"extends implements",contains:[{beginKeywords:"public protected internal private constructor"},e.UNDERSCORE_TITLE_MODE,{className:"type",begin://,excludeBegin:!0,excludeEnd:!0,relevance:0},{className:"type",begin:/[,:]\s*/,end:/[<\(,]|$/,excludeBegin:!0,returnEnd:!0},r,o]},s,{className:"meta",begin:"^#!/usr/bin/env",end:"$",illegal:"\n"},l]}};function je(...e){return e.map((e=>{return(n=e)?"string"==typeof n?n:n.source:null;var n})).join("")}var ze=function(e){const n={begin:/<\/?[A-Za-z_]/,end:">",subLanguage:"xml",relevance:0},t={variants:[{begin:/\[.+?\]\[.*?\]/,relevance:0},{begin:/\[.+?\]\(((data|javascript|mailto):|(?:http|ftp)s?:\/\/).*?\)/,relevance:2},{begin:je(/\[.+?\]\(/,/[A-Za-z][A-Za-z0-9+.-]*/,/:\/\/.*?\)/),relevance:2},{begin:/\[.+?\]\([./?&#].*?\)/,relevance:1},{begin:/\[.+?\]\(.*?\)/,relevance:0}],returnBegin:!0,contains:[{className:"string",relevance:0,begin:"\\[",end:"\\]",excludeBegin:!0,returnEnd:!0},{className:"link",relevance:0,begin:"\\]\\(",end:"\\)",excludeBegin:!0,excludeEnd:!0},{className:"symbol",relevance:0,begin:"\\]\\[",end:"\\]",excludeBegin:!0,excludeEnd:!0}]},a={className:"strong",contains:[],variants:[{begin:/_{2}/,end:/_{2}/},{begin:/\*{2}/,end:/\*{2}/}]},i={className:"emphasis",contains:[],variants:[{begin:/\*(?!\*)/,end:/\*/},{begin:/_(?!_)/,end:/_/,relevance:0}]};a.contains.push(i),i.contains.push(a);let s=[n,t];return a.contains=a.contains.concat(s),i.contains=i.contains.concat(s),s=s.concat(a,i),{name:"Markdown",aliases:["md","mkdown","mkd"],contains:[{className:"section",variants:[{begin:"^#{1,6}",end:"$",contains:s},{begin:"(?=^.+?\\n[=-]{2,}$)",contains:[{begin:"^[=-]*$"},{begin:"^",end:"\\n",contains:s}]}]},n,{className:"bullet",begin:"^[ \t]*([*+-]|(\\d+\\.))(?=\\s+)",end:"\\s+",excludeEnd:!0},a,i,{className:"quote",begin:"^>\\s+",contains:s,end:"$"},{className:"code",variants:[{begin:"(`{3,})[^`](.|\\n)*?\\1`*[ ]*"},{begin:"(~{3,})[^~](.|\\n)*?\\1~*[ ]*"},{begin:"```",end:"```+[ ]*$"},{begin:"~~~",end:"~~~+[ ]*$"},{begin:"`.+?`"},{begin:"(?=^( {4}|\\t))",contains:[{begin:"^( {4}|\\t)",end:"(\\n)$"}],relevance:0}]},{begin:"^[-\\*]{3,}",end:"$"},t,{begin:/^\[[^\n]+\]:/,returnBegin:!0,contains:[{className:"symbol",begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0},{className:"link",begin:/:\s*/,end:/$/,excludeBegin:!0}]}]}};var Pe=function(e){const n={keyword:"rec with let in inherit assert if else then",literal:"true false or and null",built_in:"import abort baseNameOf dirOf isNull builtins map removeAttrs throw toString derivation"},t={className:"subst",begin:/\$\{/,end:/\}/,keywords:n},a={className:"string",contains:[t],variants:[{begin:"''",end:"''"},{begin:'"',end:'"'}]},i=[e.NUMBER_MODE,e.HASH_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,a,{begin:/[a-zA-Z0-9-_]+(\s*=)/,returnBegin:!0,relevance:0,contains:[{className:"attr",begin:/\S+/}]}];return t.contains=i,{name:"Nix",aliases:["nixos"],keywords:n,contains:i}};var Ue=function(e){const n={$pattern:/-?[A-z\.\-]+\b/,keyword:"if else foreach return do while until elseif begin for trap data dynamicparam end break throw param continue finally in switch exit filter try process catch hidden static parameter",built_in:"ac asnp cat cd CFS chdir clc clear clhy cli clp cls clv cnsn compare copy cp cpi cpp curl cvpa dbp del diff dir dnsn ebp echo|0 epal epcsv epsn erase etsn exsn fc fhx fl ft fw gal gbp gc gcb gci gcm gcs gdr gerr ghy gi gin gjb gl gm gmo gp gps gpv group gsn gsnp gsv gtz gu gv gwmi h history icm iex ihy ii ipal ipcsv ipmo ipsn irm ise iwmi iwr kill lp ls man md measure mi mount move mp mv nal ndr ni nmo npssc nsn nv ogv oh popd ps pushd pwd r rbp rcjb rcsn rd rdr ren ri rjb rm rmdir rmo rni rnp rp rsn rsnp rujb rv rvpa rwmi sajb sal saps sasv sbp sc scb select set shcm si sl sleep sls sort sp spjb spps spsv start stz sujb sv swmi tee trcm type wget where wjb write"},t={begin:"`[\\s\\S]",relevance:0},a={className:"variable",variants:[{begin:/\$\B/},{className:"keyword",begin:/\$this/},{begin:/\$[\w\d][\w\d_:]*/}]},i={className:"string",variants:[{begin:/"/,end:/"/},{begin:/@"/,end:/^"@/}],contains:[t,a,{className:"variable",begin:/\$[A-z]/,end:/[^A-z]/}]},s={className:"string",variants:[{begin:/'/,end:/'/},{begin:/@'/,end:/^'@/}]},r=e.inherit(e.COMMENT(null,null),{variants:[{begin:/#/,end:/$/},{begin:/<#/,end:/#>/}],contains:[{className:"doctag",variants:[{begin:/\.(synopsis|description|example|inputs|outputs|notes|link|component|role|functionality)/},{begin:/\.(parameter|forwardhelptargetname|forwardhelpcategory|remotehelprunspace|externalhelp)\s+\S+/}]}]}),o={className:"built_in",variants:[{begin:"(".concat("Add|Clear|Close|Copy|Enter|Exit|Find|Format|Get|Hide|Join|Lock|Move|New|Open|Optimize|Pop|Push|Redo|Remove|Rename|Reset|Resize|Search|Select|Set|Show|Skip|Split|Step|Switch|Undo|Unlock|Watch|Backup|Checkpoint|Compare|Compress|Convert|ConvertFrom|ConvertTo|Dismount|Edit|Expand|Export|Group|Import|Initialize|Limit|Merge|Mount|Out|Publish|Restore|Save|Sync|Unpublish|Update|Approve|Assert|Build|Complete|Confirm|Deny|Deploy|Disable|Enable|Install|Invoke|Register|Request|Restart|Resume|Start|Stop|Submit|Suspend|Uninstall|Unregister|Wait|Debug|Measure|Ping|Repair|Resolve|Test|Trace|Connect|Disconnect|Read|Receive|Send|Write|Block|Grant|Protect|Revoke|Unblock|Unprotect|Use|ForEach|Sort|Tee|Where",")+(-)[\\w\\d]+")}]},l={className:"class",beginKeywords:"class enum",end:/\s*[{]/,excludeEnd:!0,relevance:0,contains:[e.TITLE_MODE]},c={className:"function",begin:/function\s+/,end:/\s*\{|$/,excludeEnd:!0,returnBegin:!0,relevance:0,contains:[{begin:"function",relevance:0,className:"keyword"},{className:"title",begin:/\w[\w\d]*((-)[\w\d]+)*/,relevance:0},{begin:/\(/,end:/\)/,className:"params",relevance:0,contains:[a]}]},g={begin:/using\s/,end:/$/,returnBegin:!0,contains:[i,s,{className:"keyword",begin:/(using|assembly|command|module|namespace|type)/}]},d={variants:[{className:"operator",begin:"(".concat("-and|-as|-band|-bnot|-bor|-bxor|-casesensitive|-ccontains|-ceq|-cge|-cgt|-cle|-clike|-clt|-cmatch|-cne|-cnotcontains|-cnotlike|-cnotmatch|-contains|-creplace|-csplit|-eq|-exact|-f|-file|-ge|-gt|-icontains|-ieq|-ige|-igt|-ile|-ilike|-ilt|-imatch|-in|-ine|-inotcontains|-inotlike|-inotmatch|-ireplace|-is|-isnot|-isplit|-join|-le|-like|-lt|-match|-ne|-not|-notcontains|-notin|-notlike|-notmatch|-or|-regex|-replace|-shl|-shr|-split|-wildcard|-xor",")\\b")},{className:"literal",begin:/(-)[\w\d]+/,relevance:0}]},u={className:"function",begin:/\[.*\]\s*[\w]+[ ]??\(/,end:/$/,returnBegin:!0,relevance:0,contains:[{className:"keyword",begin:"(".concat(n.keyword.toString().replace(/\s/g,"|"),")\\b"),endsParent:!0,relevance:0},e.inherit(e.TITLE_MODE,{endsParent:!0})]},b=[u,r,t,e.NUMBER_MODE,i,s,o,a,{className:"literal",begin:/\$(null|true|false)\b/},{className:"selector-tag",begin:/@\B/,relevance:0}],m={begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0,relevance:0,contains:[].concat("self",b,{begin:"("+["string","char","byte","int","long","bool","decimal","single","double","DateTime","xml","array","hashtable","void"].join("|")+")",className:"built_in",relevance:0},{className:"type",begin:/[\.\w\d]+/,relevance:0})};return u.contains.unshift(m),{name:"PowerShell",aliases:["ps","ps1"],case_insensitive:!0,keywords:n,contains:b.concat(l,c,g,d,m)}};var Ke=function(e){var n="[ \\t\\f]*",t=n+"[:=]"+n,a="[ \\t\\f]+",i="("+t+"|"+"[ \\t\\f]+)",s="([^\\\\\\W:= \\t\\f\\n]|\\\\.)+",r="([^\\\\:= \\t\\f\\n]|\\\\.)+",o={end:i,relevance:0,starts:{className:"string",end:/$/,relevance:0,contains:[{begin:"\\\\\\\\"},{begin:"\\\\\\n"}]}};return{name:".properties",case_insensitive:!0,illegal:/\S/,contains:[e.COMMENT("^\\s*[!#]","$"),{returnBegin:!0,variants:[{begin:s+t,relevance:1},{begin:s+a,relevance:0}],contains:[{className:"attr",begin:s,endsParent:!0,relevance:0}],starts:o},{begin:r+i,returnBegin:!0,relevance:0,contains:[{className:"meta",begin:r,endsParent:!0,relevance:0}],starts:o},{className:"attr",relevance:0,begin:r+n+"$"}]}};function He(...e){return e.map((e=>{return(n=e)?"string"==typeof n?n:n.source:null;var n})).join("")}var Ze=function(e){const n="([a-zA-Z_]\\w*[!?=]?|[-+~]@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?)",t={keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor __FILE__",built_in:"proc lambda",literal:"true false nil"},a={className:"doctag",begin:"@[A-Za-z]+"},i={begin:"#<",end:">"},s=[e.COMMENT("#","$",{contains:[a]}),e.COMMENT("^=begin","^=end",{contains:[a],relevance:10}),e.COMMENT("^__END__","\\n$")],r={className:"subst",begin:/#\{/,end:/\}/,keywords:t},o={className:"string",contains:[e.BACKSLASH_ESCAPE,r],variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/`/,end:/`/},{begin:/%[qQwWx]?\(/,end:/\)/},{begin:/%[qQwWx]?\[/,end:/\]/},{begin:/%[qQwWx]?\{/,end:/\}/},{begin:/%[qQwWx]?/},{begin:/%[qQwWx]?\//,end:/\//},{begin:/%[qQwWx]?%/,end:/%/},{begin:/%[qQwWx]?-/,end:/-/},{begin:/%[qQwWx]?\|/,end:/\|/},{begin:/\B\?(\\\d{1,3})/},{begin:/\B\?(\\x[A-Fa-f0-9]{1,2})/},{begin:/\B\?(\\u\{?[A-Fa-f0-9]{1,6}\}?)/},{begin:/\B\?(\\M-\\C-|\\M-\\c|\\c\\M-|\\M-|\\C-\\M-)[\x20-\x7e]/},{begin:/\B\?\\(c|C-)[\x20-\x7e]/},{begin:/\B\?\\?\S/},{begin:/<<[-~]?'?(\w+)\n(?:[^\n]*\n)*?\s*\1\b/,returnBegin:!0,contains:[{begin:/<<[-~]?'?/},e.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/,contains:[e.BACKSLASH_ESCAPE,r]})]}]},l="[0-9](_?[0-9])*",c={className:"number",relevance:0,variants:[{begin:`\\b([1-9](_?[0-9])*|0)(\\.(${l}))?([eE][+-]?(${l})|r)?i?\\b`},{begin:"\\b0[dD][0-9](_?[0-9])*r?i?\\b"},{begin:"\\b0[bB][0-1](_?[0-1])*r?i?\\b"},{begin:"\\b0[oO][0-7](_?[0-7])*r?i?\\b"},{begin:"\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*r?i?\\b"},{begin:"\\b0(_?[0-7])+r?i?\\b"}]},g={className:"params",begin:"\\(",end:"\\)",endsParent:!0,keywords:t},d=[o,{className:"class",beginKeywords:"class module",end:"$|;",illegal:/=/,contains:[e.inherit(e.TITLE_MODE,{begin:"[A-Za-z_]\\w*(::\\w+)*(\\?|!)?"}),{begin:"<\\s*",contains:[{begin:"("+e.IDENT_RE+"::)?"+e.IDENT_RE,relevance:0}]}].concat(s)},{className:"function",begin:He(/def\s+/,(u=n+"\\s*(\\(|;|$)",He("(?=",u,")"))),relevance:0,keywords:"def",end:"$|;",contains:[e.inherit(e.TITLE_MODE,{begin:n}),g].concat(s)},{begin:e.IDENT_RE+"::"},{className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"(!|\\?)?:",relevance:0},{className:"symbol",begin:":(?!\\s)",contains:[o,{begin:n}],relevance:0},c,{className:"variable",begin:"(\\$\\W)|((\\$|@@?)(\\w+))(?=[^@$?])(?![A-Za-z])(?![@$?'])"},{className:"params",begin:/\|/,end:/\|/,relevance:0,keywords:t},{begin:"("+e.RE_STARTERS_RE+"|unless)\\s*",keywords:"unless",contains:[{className:"regexp",contains:[e.BACKSLASH_ESCAPE,r],illegal:/\n/,variants:[{begin:"/",end:"/[a-z]*"},{begin:/%r\{/,end:/\}[a-z]*/},{begin:"%r\\(",end:"\\)[a-z]*"},{begin:"%r!",end:"![a-z]*"},{begin:"%r\\[",end:"\\][a-z]*"}]}].concat(i,s),relevance:0}].concat(i,s);var u;r.contains=d,g.contains=d;const b=[{begin:/^\s*=>/,starts:{end:"$",contains:d}},{className:"meta",begin:"^([>?]>|[\\w#]+\\(\\w+\\):\\d+:\\d+>|(\\w+-)?\\d+\\.\\d+\\.\\d+(p\\d+)?[^\\d][^>]+>)(?=[ ])",starts:{end:"$",contains:d}}];return s.unshift(i),{name:"Ruby",aliases:["rb","gemspec","podspec","thor","irb"],keywords:t,illegal:/\/\*/,contains:[e.SHEBANG({binary:"ruby"})].concat(b).concat(s).concat(d)}};var Ge=function(e){const n={className:"subst",variants:[{begin:"\\$[A-Za-z0-9_]+"},{begin:/\$\{/,end:/\}/}]},t={className:"string",variants:[{begin:'"""',end:'"""'},{begin:'"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},{begin:'[a-z]+"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE,n]},{className:"string",begin:'[a-z]+"""',end:'"""',contains:[n],relevance:10}]},a={className:"type",begin:"\\b[A-Z][A-Za-z0-9_]*",relevance:0},i={className:"title",begin:/[^0-9\n\t "'(),.`{}\[\]:;][^\n\t "'(),.`{}\[\]:;]+|[^0-9\n\t "'(),.`{}\[\]:;=]/,relevance:0},s={className:"class",beginKeywords:"class object trait type",end:/[:={\[\n;]/,excludeEnd:!0,contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{beginKeywords:"extends with",relevance:10},{begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0,relevance:0,contains:[a]},{className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,relevance:0,contains:[a]},i]},r={className:"function",beginKeywords:"def",end:/[:={\[(\n;]/,excludeEnd:!0,contains:[i]};return{name:"Scala",keywords:{literal:"true false null",keyword:"type yield lazy override def with val var sealed abstract private trait object if forSome for while throw finally protected extends import final return else break new catch super class case package default try this match continue throws implicit"},contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,t,{className:"symbol",begin:"'\\w[\\w\\d_]*(?!')"},a,r,s,e.C_NUMBER_MODE,{className:"meta",begin:"@[A-Za-z]+"}]}};var qe=function(e){return{name:"Shell Session",aliases:["console"],contains:[{className:"meta",begin:/^\s{0,3}[/~\w\d[\]()@-]*[>%$#]/,starts:{end:/[^\\](?=\s*$)/,subLanguage:"bash"}}]}};function Fe(e){return e?"string"==typeof e?e:e.source:null}function We(...e){return e.map((e=>Fe(e))).join("")}function Qe(...e){return"("+e.map((e=>Fe(e))).join("|")+")"}var Xe=function(e){const n=e.COMMENT("--","$"),t=["true","false","unknown"],a=["bigint","binary","blob","boolean","char","character","clob","date","dec","decfloat","decimal","float","int","integer","interval","nchar","nclob","national","numeric","real","row","smallint","time","timestamp","varchar","varying","varbinary"],i=["abs","acos","array_agg","asin","atan","avg","cast","ceil","ceiling","coalesce","corr","cos","cosh","count","covar_pop","covar_samp","cume_dist","dense_rank","deref","element","exp","extract","first_value","floor","json_array","json_arrayagg","json_exists","json_object","json_objectagg","json_query","json_table","json_table_primitive","json_value","lag","last_value","lead","listagg","ln","log","log10","lower","max","min","mod","nth_value","ntile","nullif","percent_rank","percentile_cont","percentile_disc","position","position_regex","power","rank","regr_avgx","regr_avgy","regr_count","regr_intercept","regr_r2","regr_slope","regr_sxx","regr_sxy","regr_syy","row_number","sin","sinh","sqrt","stddev_pop","stddev_samp","substring","substring_regex","sum","tan","tanh","translate","translate_regex","treat","trim","trim_array","unnest","upper","value_of","var_pop","var_samp","width_bucket"],s=["create table","insert into","primary key","foreign key","not null","alter table","add constraint","grouping sets","on overflow","character set","respect nulls","ignore nulls","nulls first","nulls last","depth first","breadth first"],r=i,o=["abs","acos","all","allocate","alter","and","any","are","array","array_agg","array_max_cardinality","as","asensitive","asin","asymmetric","at","atan","atomic","authorization","avg","begin","begin_frame","begin_partition","between","bigint","binary","blob","boolean","both","by","call","called","cardinality","cascaded","case","cast","ceil","ceiling","char","char_length","character","character_length","check","classifier","clob","close","coalesce","collate","collect","column","commit","condition","connect","constraint","contains","convert","copy","corr","corresponding","cos","cosh","count","covar_pop","covar_samp","create","cross","cube","cume_dist","current","current_catalog","current_date","current_default_transform_group","current_path","current_role","current_row","current_schema","current_time","current_timestamp","current_path","current_role","current_transform_group_for_type","current_user","cursor","cycle","date","day","deallocate","dec","decimal","decfloat","declare","default","define","delete","dense_rank","deref","describe","deterministic","disconnect","distinct","double","drop","dynamic","each","element","else","empty","end","end_frame","end_partition","end-exec","equals","escape","every","except","exec","execute","exists","exp","external","extract","false","fetch","filter","first_value","float","floor","for","foreign","frame_row","free","from","full","function","fusion","get","global","grant","group","grouping","groups","having","hold","hour","identity","in","indicator","initial","inner","inout","insensitive","insert","int","integer","intersect","intersection","interval","into","is","join","json_array","json_arrayagg","json_exists","json_object","json_objectagg","json_query","json_table","json_table_primitive","json_value","lag","language","large","last_value","lateral","lead","leading","left","like","like_regex","listagg","ln","local","localtime","localtimestamp","log","log10","lower","match","match_number","match_recognize","matches","max","member","merge","method","min","minute","mod","modifies","module","month","multiset","national","natural","nchar","nclob","new","no","none","normalize","not","nth_value","ntile","null","nullif","numeric","octet_length","occurrences_regex","of","offset","old","omit","on","one","only","open","or","order","out","outer","over","overlaps","overlay","parameter","partition","pattern","per","percent","percent_rank","percentile_cont","percentile_disc","period","portion","position","position_regex","power","precedes","precision","prepare","primary","procedure","ptf","range","rank","reads","real","recursive","ref","references","referencing","regr_avgx","regr_avgy","regr_count","regr_intercept","regr_r2","regr_slope","regr_sxx","regr_sxy","regr_syy","release","result","return","returns","revoke","right","rollback","rollup","row","row_number","rows","running","savepoint","scope","scroll","search","second","seek","select","sensitive","session_user","set","show","similar","sin","sinh","skip","smallint","some","specific","specifictype","sql","sqlexception","sqlstate","sqlwarning","sqrt","start","static","stddev_pop","stddev_samp","submultiset","subset","substring","substring_regex","succeeds","sum","symmetric","system","system_time","system_user","table","tablesample","tan","tanh","then","time","timestamp","timezone_hour","timezone_minute","to","trailing","translate","translate_regex","translation","treat","trigger","trim","trim_array","true","truncate","uescape","union","unique","unknown","unnest","update ","upper","user","using","value","values","value_of","var_pop","var_samp","varbinary","varchar","varying","versioning","when","whenever","where","width_bucket","window","with","within","without","year","add","asc","collation","desc","final","first","last","view"].filter((e=>!i.includes(e))),l={begin:We(/\b/,Qe(...r),/\s*\(/),keywords:{built_in:r}};return{name:"SQL",case_insensitive:!0,illegal:/[{}]|<\//,keywords:{$pattern:/\b[\w\.]+/,keyword:function(e,{exceptions:n,when:t}={}){const a=t;return n=n||[],e.map((e=>e.match(/\|\d+$/)||n.includes(e)?e:a(e)?`${e}|0`:e))}(o,{when:e=>e.length<3}),literal:t,type:a,built_in:["current_catalog","current_date","current_default_transform_group","current_path","current_role","current_schema","current_transform_group_for_type","current_user","session_user","system_time","system_user","current_time","localtime","current_timestamp","localtimestamp"]},contains:[{begin:Qe(...s),keywords:{$pattern:/[\w\.]+/,keyword:o.concat(s),literal:t,type:a}},{className:"type",begin:Qe("double precision","large object","with timezone","without timezone")},l,{className:"variable",begin:/@[a-z0-9]+/},{className:"string",variants:[{begin:/'/,end:/'/,contains:[{begin:/''/}]}]},{begin:/"/,end:/"/,contains:[{begin:/""/}]},e.C_NUMBER_MODE,e.C_BLOCK_COMMENT_MODE,n,{className:"operator",begin:/[-+*/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?/,relevance:0}]}};function Ve(e){return e?"string"==typeof e?e:e.source:null}function Je(e){return Ye("(?=",e,")")}function Ye(...e){return e.map((e=>Ve(e))).join("")}function en(...e){return"("+e.map((e=>Ve(e))).join("|")+")"}var nn=function(e){const n=Ye(/[A-Z_]/,Ye("(",/[A-Z0-9_.-]*:/,")?"),/[A-Z0-9_.-]*/),t={className:"symbol",begin:/&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/},a={begin:/\s/,contains:[{className:"meta-keyword",begin:/#?[a-z_][a-z1-9_-]+/,illegal:/\n/}]},i=e.inherit(a,{begin:/\(/,end:/\)/}),s=e.inherit(e.APOS_STRING_MODE,{className:"meta-string"}),r=e.inherit(e.QUOTE_STRING_MODE,{className:"meta-string"}),o={endsWithParent:!0,illegal:/`]+/}]}]}]};return{name:"HTML, XML",aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"],case_insensitive:!0,contains:[{className:"meta",begin://,relevance:10,contains:[a,r,s,i,{begin:/\[/,end:/\]/,contains:[{className:"meta",begin://,contains:[a,i,r,s]}]}]},e.COMMENT(//,{relevance:10}),{begin://,relevance:10},t,{className:"meta",begin:/<\?xml/,end:/\?>/,relevance:10},{className:"tag",begin:/)/,end:/>/,keywords:{name:"style"},contains:[o],starts:{end:/<\/style>/,returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag",begin:/)/,end:/>/,keywords:{name:"script"},contains:[o],starts:{end:/<\/script>/,returnEnd:!0,subLanguage:["javascript","handlebars","xml"]}},{className:"tag",begin:/<>|<\/>/},{className:"tag",begin:Ye(//,/>/,/\s/)))),end:/\/?>/,contains:[{className:"name",begin:n,relevance:0,starts:o}]},{className:"tag",begin:Ye(/<\//,Je(Ye(n,/>/))),contains:[{className:"name",begin:n,relevance:0},{begin:/>/,relevance:0,endsParent:!0}]}]}};var tn=function(e){var n="true false yes no null",t="[\\w#;/?:@&=+$,.~*'()[\\]]+",a={className:"string",relevance:0,variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/\S+/}],contains:[e.BACKSLASH_ESCAPE,{className:"template-variable",variants:[{begin:/\{\{/,end:/\}\}/},{begin:/%\{/,end:/\}/}]}]},i=e.inherit(a,{variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/[^\s,{}[\]]+/}]}),s={className:"number",begin:"\\b[0-9]{4}(-[0-9][0-9]){0,2}([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?(\\.[0-9]*)?([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?\\b"},r={end:",",endsWithParent:!0,excludeEnd:!0,keywords:n,relevance:0},o={begin:/\{/,end:/\}/,contains:[r],illegal:"\\n",relevance:0},l={begin:"\\[",end:"\\]",contains:[r],illegal:"\\n",relevance:0},c=[{className:"attr",variants:[{begin:"\\w[\\w :\\/.-]*:(?=[ \t]|$)"},{begin:'"\\w[\\w :\\/.-]*":(?=[ \t]|$)'},{begin:"'\\w[\\w :\\/.-]*':(?=[ \t]|$)"}]},{className:"meta",begin:"^---\\s*$",relevance:10},{className:"string",begin:"[\\|>]([1-9]?[+-])?[ ]*\\n( +)[^ ][^\\n]*\\n(\\2[^\\n]+\\n?)*"},{begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0,relevance:0},{className:"type",begin:"!\\w+!"+t},{className:"type",begin:"!<"+t+">"},{className:"type",begin:"!"+t},{className:"type",begin:"!!"+t},{className:"meta",begin:"&"+e.UNDERSCORE_IDENT_RE+"$"},{className:"meta",begin:"\\*"+e.UNDERSCORE_IDENT_RE+"$"},{className:"bullet",begin:"-(?=[ ]|$)",relevance:0},e.HASH_COMMENT_MODE,{beginKeywords:n,keywords:{literal:n}},s,{className:"number",begin:e.C_NUMBER_RE+"\\b",relevance:0},o,l,a],g=[...c];return g.pop(),g.push(i),r.contains=g,{name:"YAML",case_insensitive:!0,aliases:["yml"],contains:c}};!function(){"use strict";ne.registerLanguage("asciidoc",ae),ne.registerLanguage("bash",se),ne.registerLanguage("css",ue),ne.registerLanguage("diff",be),ne.registerLanguage("dockerfile",me),ne.registerLanguage("dos",he),ne.registerLanguage("gradle",pe),ne.registerLanguage("groovy",Ee),ne.registerLanguage("http",Ne),ne.registerLanguage("java",Me),ne.registerLanguage("javascript",Ce),ne.registerLanguage("json",De),ne.registerLanguage("kotlin",Ie),ne.registerLanguage("markdown",ze),ne.registerLanguage("nix",Pe),ne.registerLanguage("powershell",Ue),ne.registerLanguage("properties",Ke),ne.registerLanguage("ruby",Ze),ne.registerLanguage("scala",Ge),ne.registerLanguage("shell",qe),ne.registerLanguage("sql",Xe),ne.registerLanguage("xml",nn),ne.registerLanguage("yaml",tn),ne.configure({ignoreUnescapedHTML:!0});for(const e of document.querySelectorAll("pre.highlight > code"))ne.highlightBlock(e)}()}(); +!function(){"use strict";function t(t){const e=n('
      ');return t.prepend(e),e}function e(t,e){const o=t.querySelector(".title").textContent,c=t.querySelectorAll(".content").item(0),s=function(t,e,n){let o=t.nextElementSibling;for(;o;){if(o.matches(e))return o;if(o.matches(n))return;o=o.nextElementSibling}}(t,".colist",".listingblock");s&&c.append(s);const i=n('
      '+o+"
      ");return i.dataset.blockName=o,c.dataset.blockName=o,e.append(i),{tabElement:i,content:c}}function n(t){const e=document.createElement("template");return e.innerHTML=t,e.content.firstChild}function o(t){let e=t.previousElementSibling;for(;e&&!e.classList.contains("primary");)e=e.previousElementSibling;return e}function c(t){const e=this.textContent;window.localStorage.setItem(t,e);for(const n of document.querySelectorAll(".tab"))i(n)===t&&n.textContent===e&&s(n)}function s(t){for(const e of t.parentNode.children)e.classList.remove("selected");t.classList.add("selected");for(const e of t.parentNode.parentNode.children)e.classList.contains("content")&&(t.dataset.blockName===e.dataset.blockName?e.classList.remove("hidden"):e.classList.add("hidden"))}function i(t){const e=[];for(t of t.parentNode.querySelectorAll(".tab"))e.push(t.textContent.toLowerCase());return e.sort().join("-")}window.addEventListener("load",(function(){(function(){for(const n of document.querySelectorAll(".primary")){if(n.querySelector("div.switch"))return void console.debug("Skipping tabs due to existing blockswitches");e(n,t(n)).tabElement.classList.add("selected"),n.querySelector(".title").remove(),n.classList.add("tabs-content")}for(const t of document.querySelectorAll(".secondary")){const n=o(t);if(n){const o=e(t,n.querySelector(".tabs"));o.content.classList.add("hidden"),n.append(o.content),t.remove()}else console.error("Found secondary block with no primary sibling")}})(),function(){for(const t of document.querySelectorAll(".tab")){const e=i(t);t.addEventListener("click",c.bind(t,e)),t.textContent===window.localStorage.getItem(e)&&s(t)}}()}))}(); +!function(){var t=function(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)},e={};(function(t){(function(){var n="object"==typeof t&&t&&t.Object===Object&&t;e=n}).call(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{});var n="object"==typeof self&&self&&self.Object===Object&&self,o=e||n||Function("return this")(),r=function(){return o.Date.now()},i=/\s/;var c=function(t){for(var e=t.length;e--&&i.test(t.charAt(e)););return e},u=/^\s+/;var a=function(t){return t?t.slice(0,c(t)+1).replace(u,""):t},l=o.Symbol,f=Object.prototype,d=f.hasOwnProperty,s=f.toString,m=l?l.toStringTag:void 0;var v=function(t){var e=d.call(t,m),n=t[m];try{t[m]=void 0;var o=!0}catch(t){}var r=s.call(t);return o&&(e?t[m]=n:delete t[m]),r},p=Object.prototype.toString;var g=function(t){return p.call(t)},h=l?l.toStringTag:void 0;var y=function(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":h&&h in Object(t)?v(t):g(t)};var w=function(t){return null!=t&&"object"==typeof t};var E=function(t){return"symbol"==typeof t||w(t)&&"[object Symbol]"==y(t)},b=/^[-+]0x[0-9a-f]+$/i,L=/^0b[01]+$/i,j=/^0o[0-7]+$/i,x=parseInt;var S=function(e){if("number"==typeof e)return e;if(E(e))return NaN;if(t(e)){var n="function"==typeof e.valueOf?e.valueOf():e;e=t(n)?n+"":n}if("string"!=typeof e)return 0===e?e:+e;e=a(e);var o=L.test(e);return o||j.test(e)?x(e.slice(2),o?2:8):b.test(e)?NaN:+e},T=Math.max,O=Math.min;var N=function(e,n,o){var i,c,u,a,l,f,d=0,s=!1,m=!1,v=!0;if("function"!=typeof e)throw new TypeError("Expected a function");function p(t){var n=i,o=c;return i=c=void 0,d=t,a=e.apply(o,n)}function g(t){return d=t,l=setTimeout(y,n),s?p(t):a}function h(t){var e=t-f;return void 0===f||e>=n||e<0||m&&t-d>=u}function y(){var t=r();if(h(t))return w(t);l=setTimeout(y,function(t){var e=n-(t-f);return m?O(e,u-(t-d)):e}(t))}function w(t){return l=void 0,v&&i?p(t):(i=c=void 0,a)}function E(){var t=r(),e=h(t);if(i=arguments,c=this,f=t,e){if(void 0===l)return g(f);if(m)return clearTimeout(l),l=setTimeout(y,n),p(f)}return void 0===l&&(l=setTimeout(y,n)),a}return n=S(n)||0,t(o)&&(s=!!o.leading,u=(m="maxWait"in o)?T(S(o.maxWait)||0,n):u,v="trailing"in o?!!o.trailing:v),E.cancel=function(){void 0!==l&&clearTimeout(l),d=0,i=f=c=l=void 0},E.flush=function(){return void 0===l?a:w(r())},E};var q=function(e,n,o){var r=!0,i=!0;if("function"!=typeof e)throw new TypeError("Expected a function");return t(o)&&(r="leading"in o?!!o.leading:r,i="trailing"in o?!!o.trailing:i),N(e,n,{leading:r,maxWait:n,trailing:i})};!function(){"use strict";let t,e,n,o,r,i,c=null,u=!1;function a(){v();const t=r.get(window.location.hash),e=g(window.location.hash);t&&E(e)&&(u=!0,b("activating window location hash"),y(t.parentElement)),f()}window.addEventListener("load",(function(){if(t=document.querySelector("#toc"),e=document.querySelector("#toggle-toc"),n=document.querySelector("#content"),!t||!n)return;o=function(){const e=r(),o=[];for(let t=0;t<=e;t++)o.push("h"+(t+1)+"[id]");return n.querySelectorAll(o);function r(){let e=1;for(const n of t.querySelectorAll("ul","ol"))e=Math.max(e,i(n));return e}function i(e){let n=0;for(;e&&e!==t;)n+="UL"===e.nodeName||"OL"===e.nodeName?1:0,e=e.parentElement;return e?n:-1}}(),r=function(){const e=new Map;for(const n of t.querySelectorAll("li > a")){const t=n.getAttribute("href");t&&e.set(t,n)}return e}(),i=function(){const t=new Map;for(const e of o){const n=h(e);if(n){const o=r.get(n);if(o){const n=o.parentElement;t.set(e,n)}}}return t}(),a(),window.addEventListener("hashchange",a),window.addEventListener("scroll",l),window.addEventListener("scroll",f),window.addEventListener("resize",d),t.addEventListener("click",s),e.addEventListener("click",m)}));const l=q((function(){v(),u||p()}),50,{leading:!0}),f=N((function(){if(b("scrolling ended"),v(),u=!1,c){E(g(h(c)))||p()}else p()}),50),d=q((function(){v()}),50,{leading:!0});function s(t){if("A"===t.target.nodeName){const e=t.target.parentElement;if(e&&"back-to-index"===e.id)return;u=!0,b("activating clicked toc element"),y(t.target.parentElement)}}function m(t){t.stopPropagation();document.body.classList.toggle("show-toc")?document.documentElement.addEventListener("click",m):document.documentElement.removeEventListener("click",m)}function v(){const t=window.getComputedStyle(document.documentElement),e=parseInt(t.getPropertyValue("--layout-banner-height"),10);w()>=e?document.body.classList.add("fixed-toc"):document.body.classList.remove("fixed-toc")}function p(){b("activating top header element");const t=function(){const t=w()+45;for(let e=0;et)return o[e-1>=0?e-1:0];return o[o.length-1]}();y(i.get(t))}function g(t){for(let e=0;e=0&&e.bottom<=(window.innerHeight||document.documentElement.clientHeight)}function b(t){false}}()}(); +//# sourceMappingURL=site.js.map diff --git a/docs/v4/js/site.js.map b/docs/v4/js/site.js.map new file mode 100644 index 0000000..89de670 --- /dev/null +++ b/docs/v4/js/site.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["site/src/main/js/site/anchorrewrite.js","site/anchorrewrite.js","site/src/main/js/site/author.js","site/author.js","site/node_modules/browser-pack-flat/_prelude","site/node_modules/lodash/_baseDelay.js","site/codetools.js","site/node_modules/lodash/identity.js","site/node_modules/lodash/_apply.js","site/node_modules/lodash/_overRest.js","site/node_modules/lodash/constant.js","site/node_modules/lodash/_freeGlobal.js","site/node_modules/lodash/_root.js","site/node_modules/lodash/_Symbol.js","site/node_modules/lodash/_getRawTag.js","site/node_modules/lodash/_objectToString.js","site/node_modules/lodash/_baseGetTag.js","site/node_modules/lodash/isObject.js","site/node_modules/lodash/isFunction.js","site/node_modules/lodash/_isMasked.js","site/node_modules/lodash/_coreJsData.js","site/node_modules/lodash/_toSource.js","site/node_modules/lodash/_baseIsNative.js","site/node_modules/lodash/_getValue.js","site/node_modules/lodash/_getNative.js","site/node_modules/lodash/_defineProperty.js","site/node_modules/lodash/_baseSetToString.js","site/node_modules/lodash/_shortOut.js","site/node_modules/lodash/_setToString.js","site/node_modules/lodash/_baseRest.js","site/node_modules/lodash/_trimmedEndIndex.js","site/node_modules/lodash/_baseTrim.js","site/node_modules/lodash/isObjectLike.js","site/node_modules/lodash/isSymbol.js","site/node_modules/lodash/toNumber.js","site/node_modules/lodash/delay.js","site/src/main/js/site/codetools.js","site/node_modules/browser-pack-flat/_postlude","site/node_modules/highlight.js/lib/core.js","site/highlight.js","site/node_modules/highlight.js/lib/languages/asciidoc.js","site/node_modules/highlight.js/lib/languages/bash.js","site/node_modules/highlight.js/lib/languages/css.js","site/node_modules/highlight.js/lib/languages/diff.js","site/node_modules/highlight.js/lib/languages/dockerfile.js","site/node_modules/highlight.js/lib/languages/dos.js","site/node_modules/highlight.js/lib/languages/gradle.js","site/node_modules/highlight.js/lib/languages/groovy.js","site/node_modules/highlight.js/lib/languages/http.js","site/node_modules/highlight.js/lib/languages/java.js","site/node_modules/highlight.js/lib/languages/javascript.js","site/node_modules/highlight.js/lib/languages/json.js","site/node_modules/highlight.js/lib/languages/kotlin.js","site/node_modules/highlight.js/lib/languages/markdown.js","site/node_modules/highlight.js/lib/languages/nix.js","site/node_modules/highlight.js/lib/languages/powershell.js","site/node_modules/highlight.js/lib/languages/properties.js","site/node_modules/highlight.js/lib/languages/ruby.js","site/node_modules/highlight.js/lib/languages/scala.js","site/node_modules/highlight.js/lib/languages/shell.js","site/node_modules/highlight.js/lib/languages/sql.js","site/node_modules/highlight.js/lib/languages/xml.js","site/node_modules/highlight.js/lib/languages/yaml.js","site/src/main/js/site/highlight.js","site/src/main/js/site/tabs.js","site/tabs.js","site/toc.js","site/node_modules/lodash/now.js","site/node_modules/lodash/debounce.js","site/node_modules/lodash/throttle.js","site/src/main/js/site/toc.js"],"names":["onChange","element","document","getElementById","anchor","window","location","hash","substr","rewrites","seen","console","debug","includes","error","push","updateAnchor","JSON","parse","innerHTML","addEventListener","candidate","lastAuthorElement","classList","contains","nextElementSibling","add","markLastAuthor","_$baseDelay_3","func","wait","args","TypeError","setTimeout","apply","undefined","_$identity_25","value","_$apply_2","thisArg","length","call","nativeMax","Math","max","_$overRest_17","start","transform","arguments","index","array","Array","otherArgs","this","_$constant_23","_$freeGlobal_11","global","freeGlobal","Object","self","freeSelf","_$root_18","Function","_$Symbol_1","Symbol","objectProto","prototype","hasOwnProperty","nativeObjectToString","toString","symToStringTag","toStringTag","_$getRawTag_13","isOwn","tag","unmasked","e","result","__nativeObjectToString_16","_$objectToString_16","__symToStringTag_4","_$baseGetTag_4","_$isObject_27","type","uid","_$isFunction_26","_$coreJsData_9","maskSrcKey","exec","keys","IE_PROTO","_$isMasked_15","funcToString","_$toSource_21","reIsHostCtor","__funcProto_5","__objectProto_5","__funcToString_5","__hasOwnProperty_5","reIsNative","RegExp","replace","_$baseIsNative_5","test","_$getValue_14","object","key","_$getNative_12","_$defineProperty_10","_$baseSetToString_7","string","configurable","enumerable","writable","nativeNow","Date","now","_$shortOut_20","count","lastCalled","stamp","remaining","_$setToString_19","reWhitespace","_$trimmedEndIndex_22","charAt","reTrimStart","_$baseTrim_8","slice","_$isObjectLike_28","_$isSymbol_29","reIsBadHex","reIsBinary","reIsOctal","freeParseInt","parseInt","_$toNumber_30","other","valueOf","isBinary","_$delay_24","_$baseRest_6","onCopyButtonClick","preElement","copy","querySelector","cloneNode","hideWhenFoldedElement","querySelectorAll","parentNode","removeChild","text","innerText","navigator","clipboard","writeText","then","markClicked","bind","clearClicked","remove","onFoldUnfoldButtonClick","codeElement","unfolding","toggle","updateFoldUnfoldButton","button","unfold","label","title","codeToolsElement","createElement","className","addButtons","appendChild","numberOfButtons","hasHideWhenFoldedSpans","foldUnfoldButton","createButton","addFoldUnfoldButton","copyButton","copiedPopup","addCopyButton","buttonElement","labelElement","createTextNode","addCodeToolElements","deepFreeze","obj","Map","clear","delete","set","Error","Set","freeze","getOwnPropertyNames","forEach","name","prop","isFrozen","deepFreezeEs6","_default","default","Response","constructor","mode","data","isMatchIgnored","ignoreMatch","escapeHTML","inherit","original","objects","create","emitsWrappingTags","node","kind","HTMLRenderer","parseTree","options","buffer","classPrefix","walk","addText","openNode","sublanguage","span","closeNode","TokenTree","rootNode","children","stack","top","root","pop","closeAllNodes","toJSON","stringify","builder","_walk","static","child","every","el","join","_collapse","TokenTreeEmitter","super","addKeyword","addSublanguage","emitter","toHTML","finalize","source","re","BACKREF_RE","IDENT_RE","UNDERSCORE_IDENT_RE","NUMBER_RE","C_NUMBER_RE","BINARY_NUMBER_RE","BACKSLASH_ESCAPE","begin","relevance","APOS_STRING_MODE","end","illegal","QUOTE_STRING_MODE","PHRASAL_WORDS_MODE","COMMENT","modeOptions","C_LINE_COMMENT_MODE","C_BLOCK_COMMENT_MODE","HASH_COMMENT_MODE","NUMBER_MODE","C_NUMBER_MODE","BINARY_NUMBER_MODE","CSS_NUMBER_MODE","REGEXP_MODE","TITLE_MODE","UNDERSCORE_TITLE_MODE","METHOD_GUARD","MODES","__proto__","MATCH_NOTHING_RE","RE_STARTERS_RE","SHEBANG","opts","beginShebang","binary","map","x","concat","m","resp","END_SAME_AS_BEGIN","assign","_beginMatch","skipIfhasPrecedingDot","match","response","input","beginKeywords","parent","split","__beforeBegin","keywords","compileIllegal","_parent","isArray","either","compileMatch","compileRelevance","COMMON_KEYWORDS","compileKeywords","rawKeywords","caseInsensitive","compiledKeywords","compileList","keywordList","toLowerCase","keyword","pair","scoreForKeyword","providedScore","Number","commonKeyword","compileLanguage","language","plugins","langRe","case_insensitive","MultiRegex","matchIndexes","regexes","matchAt","position","addRule","countMatchGroups","compile","terminators","matcherRe","regexps","separator","numCaptures","regex","offset","out","substring","String","lastIndex","s","i","findIndex","matchData","splice","ResumableMultiRegex","rules","multiRegexes","regexIndex","getMatcher","matcher","resumingScanAtSamePosition","considerAll","m2","compilerExtensions","classNameAliases","compileMode","cmode","isCompiled","ext","keywordPattern","$pattern","lexemes","keywordPatternRe","beginRe","endSameAsBegin","endsWithParent","endRe","terminatorEnd","illegalRe","c","variants","cachedVariants","variant","dependencyOnParent","starts","expandOrCloneMode","mm","term","rule","buildModeRegex","BuildVuePlugin","hljs","Component","props","detectedLanguage","unknownLanguage","computed","highlighted","autoDetect","getLanguage","warn","code","highlightAuto","highlight","ignoreIllegals","autodetect","Boolean","render","class","domProps","VuePlugin","install","Vue","component","mergeHTMLPlugin","originalStream","nodeStream","resultNode","processed","nodeStack","selectStream","event","open","attributeString","attr","nodeName","attributes","close","stream","reverse","mergeStreams","_nodeStream","firstChild","nextSibling","nodeType","nodeValue","seenDeprecations","message","log","deprecated","version","escape$1","inherit$1","NO_MATCH","_$highlight_1","languages","aliases","SAFE_MODE","fixMarkupRe","LANGUAGE_NOT_FOUND","PLAINTEXT_LANGUAGE","disableAutodetect","noHighlightRe","languageDetectRe","tabReplace","useBR","__emitter","shouldNotHighlight","languageName","codeOrlanguageName","optionsOrCode","continuation","context","fire","_highlight","codeToHighlight","keywordData","matchText","processBuffer","subLanguage","modeBuffer","continuations","processSubLanguage","buf","keywordRelevance","startsWith","cssClass","processKeywords","startNewMode","endOfMode","matchPlusRemainder","matched","lexeme","endsParent","doIgnore","resumeScanAtSamePosition","doBeginMatch","newMode","beforeCallbacks","cb","skip","excludeBegin","returnBegin","doEndMatch","endMode","origin","returnEnd","excludeEnd","lastMatch","processLexeme","textBeforeMatch","err","badRule","iterations","md","list","current","unshift","item","processContinuations","processedCount","floor","illegalBy","msg","sofar","errorRaised","languageSubset","plaintext","justTextHighlightResult","results","filter","autoDetection","sorted","sort","a","b","supersetOf","best","secondBest","second_best","brPlugin","TAB_REPLACE_RE","tabReplacePlugin","highlightElement","block","classes","find","_class","blockLanguage","textContent","currentLang","resultLang","updateClassName","relavance","initHighlighting","called","wantsHighlight","highlightAll","readyState","registerAliases","aliasList","alias","lang","plugin","fixMarkup","arg","html","highlightBlock","configure","userOptions","initHighlightingOnLoad","registerLanguage","languageDefinition","error$1","rawDefinition","unregisterLanguage","listLanguages","requireLanguage","addPlugin","upgradePluginAPI","vuePlugin","debugMode","safeMode","versionString","HLJS","__concat_2","__source_2","_$asciidoc_2","STRONG","EMPHASIS","__concat_3","__source_3","_$bash_3","VAR","BRACED_VAR","SUBST","HERE_DOC","QUOTE_STRING","ARITHMETIC","KNOWN_SHEBANG","FUNCTION","literal","built_in","TAGS","MEDIA_FEATURES","PSEUDO_CLASSES","PSEUDO_ELEMENTS","ATTRIBUTES","lookahead","__source_4","__concat_4","_$css_4","modes","IMPORTANT","HEXCOLOR","ATTRIBUTE_SELECTOR_MODE","__MODES_4","STRINGS","keyframePosition","attribute","_$diff_5","_$dockerfile_6","_$dos_7","_$gradle_8","__lookahead_9","__source_9","__concat_9","_$groovy_9","REGEXP","NUMBER","STRING","__concat_10","__source_10","_$http_10","VERSION","HEADER","HEADERS_AND_BODY","frac","hexDigits","NUMERIC","_$java_11","JAVA_IDENT_RE","KEYWORDS","ANNOTATION","__IDENT_RE_12","LITERALS","BUILT_INS","__lookahead_12","__concat_12","__source_12","_$javascript_12","IDENT_RE$1","FRAGMENT","XML_TAG","isTrulyOpeningTag","afterMatchIndex","nextChar","after","indexOf","hasClosingTag","KEYWORDS$1","decimalInteger","HTML_TEMPLATE","CSS_TEMPLATE","TEMPLATE_STRING","SUBST_INTERNALS","SUBST_AND_COMMENTS","PARAMS_CONTAINS","PARAMS","exports","_$json_13","ALLOWED_COMMENTS","TYPES","VALUE_CONTAINER","OBJECT","ARRAY","__frac_14","__hexDigits_14","__NUMERIC_14","_$kotlin_14","LABEL","VARIABLE","ANNOTATION_USE_SITE","KOTLIN_NUMBER_MODE","KOTLIN_NESTED_COMMENT","KOTLIN_PAREN_TYPE","KOTLIN_PAREN_TYPE2","__concat_15","__source_15","_$markdown_15","INLINE_HTML","LINK","BOLD","ITALIC","CONTAINABLE","_$nix_16","NIX_KEYWORDS","ANTIQUOTE","EXPRESSIONS","_$powershell_17","BACKTICK_ESCAPE","APOS_STRING","PS_COMMENT","CMDLETS","PS_CLASS","PS_FUNCTION","PS_USING","PS_ARGUMENTS","PS_METHODS","GENTLEMANS_SET","PS_TYPE","_$properties_18","WS0","EQUAL_DELIM","WS_DELIM","DELIM","KEY_ALPHANUM","KEY_OTHER","DELIM_AND_VALUE","__concat_19","__source_19","_$ruby_19","RUBY_METHOD_RE","RUBY_KEYWORDS","YARDOCTAG","IRB_OBJECT","COMMENT_MODES","digits","RUBY_DEFAULT_CONTAINS","IRB_DEFAULT","_$scala_20","TYPE","NAME","CLASS","METHOD","_$shell_21","__source_22","__concat_22","__either_22","_$sql_22","COMMENT_MODE","RESERVED_FUNCTIONS","COMBOS","FUNCTIONS","FUNCTION_CALL","exceptions","when","qualifyFn","reduceRelevancy","__source_23","__lookahead_23","__concat_23","__either_23","_$xml_23","TAG_NAME_RE","XML_ENTITIES","XML_META_KEYWORDS","XML_META_PAR_KEYWORDS","APOS_META_STRING_MODE","QUOTE_META_STRING_MODE","TAG_INTERNALS","_$yaml_24","URI_CHARACTERS","CONTAINER_STRING","TIMESTAMP","VALUE_MODES","ignoreUnescapedHTML","createTabsElement","primaryElement","tabsElement","createElementFromHtml","prepend","createTab","blockElement","content","colist","selector","stopSelector","sibling","matches","append","tabElement","dataset","blockName","template","findPrimaryElement","secondaryElement","previousElementSibling","onTabClick","tabId","localStorage","setItem","getTabId","select","id","tab","addTabs","getItem","configureTabs","_$isObject_10","_$freeGlobal_4","_$root_7","_$now_13","_$trimmedEndIndex_8","_$baseTrim_3","_$getRawTag_5","__nativeObjectToString_6","_$objectToString_6","__symToStringTag_2","_$baseGetTag_2","_$isObjectLike_11","_$isSymbol_12","_$toNumber_15","nativeMin","min","_$debounce_9","lastArgs","lastThis","maxWait","timerId","lastCallTime","lastInvokeTime","leading","maxing","trailing","invokeFunc","time","leadingEdge","timerExpired","shouldInvoke","timeSinceLastCall","trailingEdge","timeWaiting","remainingWait","debounced","isInvoking","clearTimeout","cancel","flush","_$throttle_14","tocElement","toggleTocElement","contentElement","headingElements","hrefToTocAnchorElement","headingElementToTocElement","lastActiveTocElement","disableOnScroll","onLocationHashChange","updateFixedPositionClass","tocAnchorElement","get","headingElement","getHeadingElementByHref","isInViewport","activateTocElement","parentElement","onEndScroll","maxHeadingLevel","getMaxHeadingLevel","headingSelectors","headingLevel","listElement","getHeadingLevel","findHeadingElements","href","getAttribute","buildHrefToTocAnchorElement","getChildAnchorHref","buildHeadingElementToTocElement","onScroll","onResize","onTocElementClick","onToggleTocClick","activateTopHeadingTocElement","target","stopPropagation","body","documentElement","removeEventListener","computedStyle","getComputedStyle","bannerHeight","getPropertyValue","getTop","topHeadingElement","topHeadingPos","offsetTop","getTopHeading","achorElement","deactivateTocElement","scrollTop","rect","getBoundingClientRect","bottom","innerHeight","clientHeight"],"mappings":"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CL9F,UAAW,cAKbka,EAAe,CACnBla,UAAW,SACX2F,MAAO,IAAKG,IAAK,IACjBlP,SAAU,CACRkX,EAAKpI,iBACLoU,EACAE,IAGJA,EAAMpjB,SAAST,KAAK+jB,GACpB,MASMC,EAAa,CACjBxU,MAAO,SACPG,IAAK,OACLlP,SAAU,CACR,CAAE+O,MAAO,gBAAiB3F,UAAW,UACrC8N,EAAKvH,YACLuT,IAcEM,EAAgBtM,EAAK3G,QAAQ,CACjCG,OAAQ,IAZa,CACrB,OACA,OACA,MACA,KACA,MACA,MACA,OACA,OACA,QAG2B7C,KAAK,QAChCmB,UAAW,KAEPyU,EAAW,CACfra,UAAW,WACX2F,MAAO,4BACPwO,aAAa,EACbvd,SAAU,CAACkX,EAAKvL,QAAQuL,EAAKlH,WAAY,CAACjB,MAAO,gBACjDC,UAAW,GAGb,MAAO,CACLlE,KAAM,OACN2P,QAAS,CAAC,KAAM,OAChB9I,SAAU,CACRkE,SAAU,gBACVnD,QACE,+DACFgR,QACE,aACFC,SAGE,6uBAeJ3jB,SAAU,CACRwjB,EACAtM,EAAK3G,UACLkT,EACAF,EACArM,EAAKxH,kBACL2T,EACAC,EA3EkB,CACpBla,UAAW,GACX2F,MAAO,OAGW,CAClB3F,UAAW,SACX2F,MAAO,IAAKG,IAAK,KAuEfgU,GF0wFN,EG76FA,MAuBMU,GAAO,CACX,IACA,OACA,UACA,UACA,QACA,QACA,IACA,aACA,OACA,SACA,SACA,UACA,OACA,OACA,KACA,MACA,UACA,MACA,MACA,KACA,KACA,KACA,WACA,aACA,SACA,SACA,OACA,KACA,KACA,KACA,KACA,KACA,KACA,SACA,SACA,OACA,IACA,SACA,MACA,QACA,MACA,MACA,QACA,SACA,KACA,OACA,OACA,OACA,MACA,SACA,KACA,IACA,IACA,QACA,OACA,UACA,OACA,SACA,UACA,MACA,QACA,QACA,KACA,WACA,QACA,KACA,QACA,OACA,KACA,KACA,MACA,SAGIC,GAAiB,CACrB,YACA,cACA,eACA,QACA,cACA,cACA,sBACA,gBACA,eACA,eACA,gBACA,OACA,SACA,QACA,kBACA,aACA,cACA,iBACA,kBACA,UACA,uBACA,mBACA,yBACA,+BACA,aACA,OACA,YACA,SACA,QAEA,YACA,YACA,aACA,cAIIC,GAAiB,CACrB,SACA,WACA,QACA,UACA,UACA,UACA,UACA,MACA,WACA,OACA,QACA,UACA,QACA,cACA,gBACA,aACA,SACA,QACA,gBACA,eACA,MACA,OACA,eACA,QACA,gBACA,WACA,UACA,KACA,OACA,aACA,eACA,OACA,OACA,aACA,MACA,YACA,UACA,iBACA,eACA,mBACA,cACA,aACA,eACA,WACA,eACA,OACA,oBACA,YACA,aACA,WACA,QACA,OACA,QACA,SACA,gBACA,eACA,QACA,UACA,SAIIC,GAAkB,CACtB,QACA,WACA,SACA,MACA,aACA,eACA,aACA,gBACA,SACA,OACA,cACA,YACA,UACA,kBAGIC,GAAa,CACjB,gBACA,cACA,aACA,YACA,kBACA,sBACA,qBACA,sBACA,4BACA,iBACA,uBACA,4BACA,OACA,sBACA,aACA,wBACA,kBACA,mBACA,mBACA,oBACA,sBACA,oBACA,kBACA,SACA,gBACA,sBACA,4BACA,6BACA,sBACA,sBACA,kBACA,eACA,eACA,sBACA,sBACA,qBACA,sBACA,qBACA,cACA,oBACA,oBACA,oBACA,gBACA,eACA,qBACA,qBACA,qBACA,iBACA,eACA,aACA,mBACA,yBACA,0BACA,mBACA,mBACA,eACA,SACA,uBACA,aACA,aACA,cACA,eACA,eACA,eACA,QACA,OACA,YACA,QACA,eACA,cACA,aACA,cACA,oBACA,oBACA,oBACA,cACA,eACA,UACA,UACA,oBACA,gBACA,SACA,YACA,UACA,cACA,SACA,OACA,aACA,iBACA,YACA,YACA,cACA,YACA,QACA,OACA,eACA,cACA,wBACA,eACA,yBACA,YACA,mBACA,iBACA,eACA,aACA,eACA,yBACA,0BACA,cACA,SACA,UACA,OACA,oBACA,kBACA,mBACA,WACA,UACA,UACA,kBACA,OACA,iBACA,cACA,aACA,mBACA,sBACA,kBACA,SACA,gBACA,cACA,eACA,aACA,QACA,OACA,aACA,YACA,aACA,YACA,WACA,YACA,WACA,YACA,SACA,OACA,SACA,aACA,kBACA,UACA,QACA,UACA,UACA,gBACA,iBACA,gBACA,gBACA,WACA,gBACA,aACA,aACA,UACA,iBACA,eACA,gBACA,cACA,mBACA,oBACA,oBACA,cACA,qBACA,iBACA,WACA,SACA,SACA,QACA,MACA,WACA,eACA,aACA,kBACA,kBACA,wBACA,uBACA,wBACA,cACA,gBACA,iBACA,cACA,iBACA,0BACA,MACA,YACA,mBACA,kBACA,aACA,mBACA,sBACA,sBACA,6BACA,eACA,iBACA,aACA,cACA,SACA,QACA,aACA,eACA,YACA,WAGAxK,UAsBF,SAASyK,GAAU1V,GACjB,OAOF,YAAmBhO,GAEjB,OADeA,EAAKoQ,KAAKC,GApB3B,SAAgBrC,GACd,OAAKA,EACa,iBAAPA,EAAwBA,EAE5BA,EAAGD,OAHM,IHq7FlB,CGl6FiC4V,CAAOtT,KAAI/C,KAAK,GHm7FjD,CG37FSsW,CAAO,MAAO5V,EAAI,IHk7F3B,CGpxFA,IAAA6V,GA3IA,SAAalN,GACX,MAAMmN,EArdM,CAACnN,IACN,CACLoN,UAAW,CACTlb,UAAW,OACX2F,MAAO,cAETwV,SAAU,CACRnb,UAAW,SACX2F,MAAO,oCAETyV,wBAAyB,CACvBpb,UAAW,gBACX2F,MAAO,KACPG,IAAK,KACLC,QAAS,IACTnP,SAAU,CACRkX,EAAKjI,iBACLiI,EAAK9H,sBAocGqV,CAAMvN,GAWdwN,EAAU,CACdxN,EAAKjI,iBACLiI,EAAK9H,mBAGP,MAAO,CACLtE,KAAM,MACNsI,kBAAkB,EAClBjE,QAAS,UACTwC,SAAU,CACRgT,iBAAkB,WAEpBpP,iBAAkB,CAGhBoP,iBAAkB,gBAEpB3kB,SAAU,CACRkX,EAAKzH,qBAxBa,CACpBV,MAAO,gCA2BLmI,EAAKpH,gBACL,CACE1G,UAAW,cACX2F,MAAO,kBACPC,UAAW,GAEb,CACE5F,UAAW,iBACX2F,MAAO,6BACPC,U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,EAAKzH,uBAGT6V,EACAc,GV2iIN,EW1tIA,MAAMC,GAAW,2BACXF,GAAW,CACf,KACA,KACA,KACA,KACA,MACA,QACA,UACA,MACA,MACA,WACA,KACA,SACA,OACA,OACA,QACA,QACA,aACA,OACA,QACA,OACA,UACA,MACA,SACA,WACA,SACA,SACA,MACA,QACA,QACA,QAIA,WACA,QACA,QACA,SACA,SACA,OACA,SACA,WAEIG,GAAW,CACf,OACA,QACA,OACA,YACA,MACA,YAoFIC,GAAY,GAAG1V,OAlCI,CACvB,cACA,aACA,gBACA,eAEA,UACA,UAEA,OACA,WACA,QACA,aACA,WACA,YACA,qBACA,YACA,qBACA,SACA,YAGyB,CACzB,YACA,OACA,QACA,UACA,SACA,WACA,eACA,SACA,UA9EY,CACZ,OACA,WACA,SACA,OACA,OACA,SACA,SACA,SACA,WACA,UACA,QACA,SACA,MACA,MACA,UACA,UACA,QACA,UACA,OACA,UACA,eACA,aACA,aACA,YACA,cACA,cACA,eACA,QACA,aACA,oBACA,cACA,gBACA,iBACA,UAGkB,CAClB,YACA,gBACA,aACA,iBACA,cACA,YACA,aAgEF,SAAS2V,GAAUjY,GACjB,OAAOkY,GAAO,MAAOlY,EAAI,IX+tI3B,CWxtIA,SAASkY,MAAUlmB,GAEjB,OADeA,EAAKoQ,KAAKC,IAAM8V,OApBjBnY,EAoBwBqC,GAlBpB,iBAAPrC,EAAwBA,EAE5BA,EAAGD,OAHM,KADlB,IAAgBC,CAoB0B,IAAEV,KAAK,GXguIjD,CW/yHA,IAAA8Y,GAraA,SAAoBzP,GAQlB,MAMM0P,EAAaP,GACbQ,EACG,KADHA,EAEC,MAEDC,EAAU,CACd/X,MAAO,sBACPG,IAAK,4BAKL6X,kBAAmB,CAAC3V,EAAOC,KACzB,MAAM2V,EAAkB5V,EAAM,GAAGpQ,OAASoQ,EAAM3P,MAC1CwlB,EAAW7V,EAAME,MAAM0V,GAIZ,MAAbC,EAMa,MAAbA,IA9Bc,EAAC7V,GAAS8V,YAC9B,MAAMhkB,EAAM,KAAOkO,EAAM,GAAG5K,MAAM,GAElC,OAAgB,IADJ4K,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W,SACX2F,MAAO,uBAmEL6c,EACAG,EACAD,EACA5U,EAAKtH,cA5HU,CACjBxG,UAAW,OACX2F,MAAO,enBi4MX,EoB/2MA,IAAAid,GApBA,SAAe9U,GACb,MAAO,CACLpM,KAAM,gBACN2P,QAAS,CAAE,WACXza,SAAU,CACR,CACEoJ,UAAW,OAIX2F,MAAO,iCACP4H,OAAQ,CACNzH,IAAK,gBACL8M,YAAa,UpBq5MvB,EqBl6MA,SAASiQ,GAAO1d,GACd,OAAKA,EACa,iBAAPA,EAAwBA,EAE5BA,EAAGD,OAHM,IrBm7MlB,CqBz6MA,SAAS4d,MAAU3rB,GAEjB,OADeA,EAAKoQ,KAAKC,GAAMqb,GAAOrb,KAAI/C,KAAK,GrBi7MjD,CqBt6MA,SAASse,MAAU5rB,GAEjB,MADe,IAAMA,EAAKoQ,KAAKC,GAAMqb,GAAOrb,KAAI/C,KAAK,KAAO,GrBi7M9D,CqBxxLA,IAAAue,GA/oBA,SAAalV,GACX,MAAMmV,EAAenV,EAAK5H,QAAQ,KAAM,KAmBlCgX,EAAW,CACf,OACA,QAGA,WAUI2B,EAAQ,CACZ,SACA,SACA,OACA,UACA,OACA,YACA,OACA,OACA,MACA,WACA,UACA,QACA,MACA,UACA,WACA,QACA,QACA,WACA,UACA,OACA,MACA,WACA,OACA,YACA,UACA,UACA,aAmYIqE,EAAqB,CACzB,MACA,OACA,YACA,OACA,OACA,MACA,OACA,OACA,UACA,WACA,OACA,MACA,OACA,QACA,YACA,aACA,YACA,aACA,QACA,UACA,MACA,UACA,cACA,QACA,aACA,gBACA,cACA,cACA,iBACA,aACA,aACA,uBACA,aACA,MACA,aACA,OACA,UACA,KACA,MACA,QACA,QACA,MACA,MACA,MACA,YACA,QACA,SACA,eACA,kBACA,kBACA,WACA,iBACA,QACA,OACA,YACA,YACA,aACA,iBACA,UACA,aACA,WACA,WACA,WACA,aACA,MACA,OACA,OACA,aACA,cACA,YACA,kBACA,MACA,MACA,OACA,YACA,kBACA,QACA,OACA,aACA,SACA,QACA,WACA,UACA,WACA,gBAwBIC,EAAS,CACb,eACA,cACA,cACA,cACA,WACA,cACA,iBACA,gBACA,cACA,gBACA,gBACA,eACA,cACA,aACA,cACA,iBAGIC,EAAYF,EAEZnG,EAAW,CArff,MACA,OACA,MACA,WACA,QACA,MACA,MACA,MACA,QACA,YACA,wBACA,KACA,aACA,OACA,aACA,KACA,OACA,SACA,gBACA,MACA,QACA,cACA,kBACA,UACA,SACA,SACA,OACA,UACA,OACA,KACA,OACA,SACA,cACA,WACA,OACA,OACA,OACA,UACA,OACA,cACA,YACA,mBACA,QACA,aACA,OACA,QACA,WACA,UACA,UACA,SACA,SACA,YACA,UACA,aACA,WACA,UACA,OACA,OACA,gBACA,MACA,OACA,QACA,YACA,aACA,SACA,QACA,OACA,YACA,UACA,kBACA,eACA,kCACA,eACA,eACA,cACA,iBACA,eACA,oBACA,eACA,eACA,mCACA,eACA,SACA,QACA,OACA,MACA,aACA,MACA,UACA,WACA,UACA,UACA,SACA,SACA,aACA,QACA,WACA,gBACA,aACA,WACA,SACA,OACA,UACA,OACA,UACA,OACA,QACA,MACA,YACA,gBACA,WACA,SACA,SACA,QACA,SACA,OACA,UACA,SACA,MACA,WACA,UACA,QACA,QACA,SACA,cACA,QACA,QACA,MACA,UACA,YACA,OACA,OACA,OACA,WACA,SACA,MACA,SACA,QACA,QACA,WACA,SACA,SACA,OACA,OACA,WACA,KACA,YACA,UACA,QACA,QACA,cACA,SACA,MACA,UACA,YACA,eACA,WACA,OACA,KACA,OACA,aACA,gBACA,cACA,cACA,iBACA,aACA,aACA,uBACA,aACA,MACA,WACA,QACA,aACA,UACA,OACA,UACA,OACA,OACA,aACA,UACA,KACA,QACA,YACA,iBACA,MACA,QACA,QACA,QACA,eACA,kBACA,UACA,MACA,SACA,QACA,SACA,MACA,SACA,MACA,WACA,SACA,QACA,WACA,WACA,UACA,QACA,QACA,MACA,KACA,OACA,YACA,MACA,YACA,QACA,OACA,SACA,UACA,eACA,oBACA,KACA,SACA,MACA,OACA,KACA,MACA,OACA,OACA,KACA,QACA,MACA,QACA,OACA,WACA,UACA,YACA,YACA,UACA,MACA,UACA,eACA,kBACA,kBACA,SACA,UACA,WACA,iBACA,QACA,WACA,YACA,UACA,UACA,YACA,MACA,QACA,OACA,QACA,OACA,YACA,MACA,aACA,cACA,YACA,YACA,aACA,iBACA,UACA,aACA,WACA,WACA,WACA,UACA,SACA,SACA,UACA,SACA,QACA,WACA,SACA,MACA,aACA,OACA,UACA,YACA,QACA,SACA,SACA,SACA,OACA,SACA,YACA,eACA,MACA,OACA,UACA,MACA,OACA,OACA,WACA,OACA,WACA,eACA,MACA,eACA,WACA,aACA,OACA,QACA,SACA,aACA,cACA,cACA,SACA,YACA,kBACA,WACA,MACA,YACA,SACA,cACA,cACA,QACA,cACA,MACA,OACA,OACA,OACA,YACA,gBACA,kBACA,KACA,WACA,YACA,kBACA,cACA,QACA,UACA,OACA,aACA,OACA,WACA,UACA,QACA,SACA,UACA,SACA,YACA,QACA,OACA,QACA,QACA,SACA,WACA,UACA,WACA,YACA,UACA,UACA,aACA,OACA,WACA,QACA,eACA,SACA,OACA,SACA,UACA,OAzXA,MACA,MACA,YACA,OACA,QACA,QACA,OACA,QA0f0DhH,QAAQzM,IAC1D4Z,EAAmBjtB,SAASqT,KAchC+Z,EAAgB,CACpB1d,MAAOmd,GAAO,KAAMC,MAAUK,GAAY,SAC1C7a,SAAU,CACRgS,SAAU6I,IAmBd,MAAO,CACL1hB,KAAM,MACNsI,kBAAkB,EAElBjE,QAAS,WACTwC,SAAU,CACRkE,SAAU,YACVnD,QArBJ,SAAyB0L,GAAMsO,WAACA,EAAUC,KAAEA,GAAQ,CAAA,GAClD,MAAMC,EAAYD,EAElB,OADAD,EAAaA,GAAc,GACpBtO,EAAKzN,KAAK4N,GACXA,EAAKnN,MAAM,WAAasb,EAAWrtB,SAASkf,GACvCA,EACEqO,EAAUrO,GACZ,GAAGA,MAEHA,G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","file":"site.js","sourcesContent":["/*\n * Copyright 2021 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the 'License');\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an 'AS IS' BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n(function () {\n \"use strict\";\n\n window.addEventListener(\"load\", onChange);\n window.addEventListener(\"hashchange\", onChange);\n\n function onChange() {\n const element = document.getElementById(\"anchor-rewrite\");\n const anchor = window.location.hash.substr(1);\n if (element && anchor) {\n const rewites = JSON.parse(element.innerHTML);\n updateAnchor(anchor, rewites);\n }\n }\n\n function updateAnchor(anchor, rewrites) {\n const seen = [anchor];\n console.debug(anchor);\n while (rewrites[anchor]) {\n anchor = rewrites[anchor];\n if (seen.includes(anchor)) {\n console.error(\"Skipping circular anchor update\");\n return;\n }\n seen.push(anchor);\n }\n window.location.hash = anchor;\n }\n})();\n","/*\n * Copyright 2021 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the 'License');\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an 'AS IS' BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n(function () {\n \"use strict\";\n\n window.addEventListener(\"load\", onChange);\n window.addEventListener(\"hashchange\", onChange);\n\n function onChange() {\n const element = document.getElementById(\"anchor-rewrite\");\n const anchor = window.location.hash.substr(1);\n if (element && anchor) {\n const rewites = JSON.parse(element.innerHTML);\n updateAnchor(anchor, rewites);\n }\n }\n\n function updateAnchor(anchor, rewrites) {\n const seen = [anchor];\n console.debug(anchor);\n while (rewrites[anchor]) {\n anchor = rewrites[anchor];\n if (seen.includes(anchor)) {\n console.error(\"Skipping circular anchor update\");\n return;\n }\n seen.push(anchor);\n }\n window.location.hash = anchor;\n }\n})();\n","/*\n * Copyright 2021 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the 'License');\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an 'AS IS' BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n(function () {\n \"use strict\";\n\n markLastAuthor();\n\n function markLastAuthor() {\n let candidate = document.getElementById(\"author\");\n let lastAuthorElement = candidate;\n while (candidate) {\n if (candidate.classList.contains(\"author\")) {\n lastAuthorElement = candidate;\n }\n candidate = candidate.nextElementSibling;\n }\n if (lastAuthorElement) {\n lastAuthorElement.classList.add(\"last-author\");\n }\n }\n})();\n","/*\n * Copyright 2021 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the 'License');\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an 'AS IS' BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n(function () {\n \"use strict\";\n\n markLastAuthor();\n\n function markLastAuthor() {\n let candidate = document.getElementById(\"author\");\n let lastAuthorElement = candidate;\n while (candidate) {\n if (candidate.classList.contains(\"author\")) {\n lastAuthorElement = candidate;\n }\n candidate = candidate.nextElementSibling;\n }\n if (lastAuthorElement) {\n lastAuthorElement.classList.add(\"last-author\");\n }\n }\n})();\n","(function(){\n","/** Error message constants. */\nvar FUNC_ERROR_TEXT = 'Expected a function';\n\n/**\n * The base implementation of `_.delay` and `_.defer` which accepts `args`\n * to provide to `func`.\n *\n * @private\n * @param {Function} func The function to delay.\n * @param {number} wait The number of milliseconds to delay invocation.\n * @param {Array} args The arguments to provide to `func`.\n * @returns {number|Object} Returns the timer id or timeout object.\n */\nfunction baseDelay(func, wait, args) {\n if (typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n return setTimeout(function() { func.apply(undefined, args); }, wait);\n}\n\nmodule.exports = baseDelay;\n","/*\n * Copyright 2021 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the 'License');\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an 'AS IS' BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n(function () {\n \"use strict\";\n\n const delay = require(\"lodash/delay\");\n\n addCodeToolElements();\n\n function addCodeToolElements() {\n for (const preElement of document.querySelectorAll(\".doc pre.highlight\")) {\n const codeToolsElement = document.createElement(\"div\");\n codeToolsElement.className = \"codetools\";\n if (addButtons(preElement, codeToolsElement)) {\n preElement.appendChild(codeToolsElement);\n }\n }\n\n function addButtons(preElement, codeToolsElement) {\n let numberOfButtons = 0;\n if (hasHideWhenFoldedSpans(preElement)) {\n addFoldUnfoldButton(preElement, codeToolsElement);\n numberOfButtons++;\n }\n if (window.navigator.clipboard) {\n addCopyButton(preElement, codeToolsElement);\n numberOfButtons++;\n }\n return numberOfButtons > 0;\n }\n\n function hasHideWhenFoldedSpans(preElement) {\n return !!preElement.querySelector(\"span.hide-when-folded\");\n }\n\n function addFoldUnfoldButton(preElement, codeToolsElement) {\n const foldUnfoldButton = createButton();\n updateFoldUnfoldButton(foldUnfoldButton, true);\n foldUnfoldButton.addEventListener(\n \"click\",\n onFoldUnfoldButtonClick.bind(foldUnfoldButton, preElement)\n );\n codeToolsElement.appendChild(foldUnfoldButton);\n }\n\n function addCopyButton(preElement, codeToolsElement) {\n const copyButton = createButton(\"Copy to clipboard\", \"copy-button\");\n copyButton.addEventListener(\n \"click\",\n onCopyButtonClick.bind(copyButton, preElement)\n );\n copyButton.addEventListener(\"mouseleave\", clearClicked.bind(copyButton));\n copyButton.addEventListener(\"blur\", clearClicked.bind(copyButton));\n const copiedPopup = document.createElement(\"span\");\n copyButton.appendChild(copiedPopup);\n copiedPopup.className = \"copied\";\n codeToolsElement.appendChild(copyButton);\n }\n\n function createButton(label, className) {\n const buttonElement = document.createElement(\"button\");\n buttonElement.className = className;\n buttonElement.title = label;\n buttonElement.type = \"button\";\n const labelElement = document.createElement(\"span\");\n labelElement.appendChild(document.createTextNode(label));\n labelElement.className = \"label\";\n buttonElement.appendChild(labelElement);\n return buttonElement;\n }\n }\n\n function onCopyButtonClick(preElement) {\n const codeElement = preElement.querySelector(\"code\");\n const copy = codeElement.cloneNode(true);\n for (const hideWhenFoldedElement of copy.querySelectorAll(\n \".hide-when-unfolded\"\n )) {\n hideWhenFoldedElement.parentNode.removeChild(hideWhenFoldedElement);\n }\n const text = copy.innerText;\n if (text) {\n window.navigator.clipboard\n .writeText(text + \"\\n\")\n .then(markClicked.bind(this));\n }\n }\n\n function markClicked() {\n this.classList.add(\"clicked\");\n }\n\n function clearClicked() {\n this.classList.remove(\"clicked\");\n }\n\n function onFoldUnfoldButtonClick(preElement) {\n const codeElement = preElement.querySelector(\"code\");\n const unfolding = !codeElement.classList.contains(\"unfolded\");\n codeElement.classList.remove(unfolding ? \"folding\" : \"unfolding\");\n codeElement.classList.add(unfolding ? \"unfolding\" : \"folding\");\n delay(function () {\n codeElement.classList.remove(unfolding ? \"unfolding\" : \"folding\");\n codeElement.classList.toggle(\"unfolded\");\n }, 1100);\n updateFoldUnfoldButton(this, !unfolding);\n }\n\n function updateFoldUnfoldButton(button, unfold) {\n const label = unfold ? \"Expand folded text\" : \"Collapse foldable text\";\n button.classList.remove(unfold ? \"fold-button\" : \"unfold-button\");\n button.classList.add(unfold ? \"unfold-button\" : \"fold-button\");\n button.querySelector(\"span.label\").innerText = label;\n button.title = label;\n }\n})();\n","/**\n * This method returns the first argument it receives.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Util\n * @param {*} value Any value.\n * @returns {*} Returns `value`.\n * @example\n *\n * var object = { 'a': 1 };\n *\n * console.log(_.identity(object) === object);\n * // => true\n */\nfunction identity(value) {\n return value;\n}\n\nmodule.exports = identity;\n","/**\n * A faster alternative to `Function#apply`, this function invokes `func`\n * with the `this` binding of `thisArg` and the arguments of `args`.\n *\n * @private\n * @param {Function} func The function to invoke.\n * @param {*} thisArg The `this` binding of `func`.\n * @param {Array} args The arguments to invoke `func` with.\n * @returns {*} Returns the result of `func`.\n */\nfunction apply(func, thisArg, args) {\n switch (args.length) {\n case 0: return func.call(thisArg);\n case 1: return func.call(thisArg, args[0]);\n case 2: return func.call(thisArg, args[0], args[1]);\n case 3: return func.call(thisArg, args[0], args[1], args[2]);\n }\n return func.apply(thisArg, args);\n}\n\nmodule.exports = apply;\n","var apply = require('./_apply');\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max;\n\n/**\n * A specialized version of `baseRest` which transforms the rest array.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @param {Function} transform The rest array transform.\n * @returns {Function} Returns the new function.\n */\nfunction overRest(func, start, transform) {\n start = nativeMax(start === undefined ? (func.length - 1) : start, 0);\n return function() {\n var args = arguments,\n index = -1,\n length = nativeMax(args.length - start, 0),\n array = Array(length);\n\n while (++index < length) {\n array[index] = args[start + index];\n }\n index = -1;\n var otherArgs = Array(start + 1);\n while (++index < start) {\n otherArgs[index] = args[index];\n }\n otherArgs[start] = transform(array);\n return apply(func, this, otherArgs);\n };\n}\n\nmodule.exports = overRest;\n","/**\n * Creates a function that returns `value`.\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Util\n * @param {*} value The value to return from the new function.\n * @returns {Function} Returns the new constant function.\n * @example\n *\n * var objects = _.times(2, _.constant({ 'a': 1 }));\n *\n * console.log(objects);\n * // => [{ 'a': 1 }, { 'a': 1 }]\n *\n * console.log(objects[0] === objects[1]);\n * // => true\n */\nfunction constant(value) {\n return function() {\n return value;\n };\n}\n\nmodule.exports = constant;\n","/** Detect free variable `global` from Node.js. */\nvar freeGlobal = typeof global == 'object' && global && global.Object === Object && global;\n\nmodule.exports = freeGlobal;\n","var freeGlobal = require('./_freeGlobal');\n\n/** Detect free variable `self`. */\nvar freeSelf = typeof self == 'object' && self && self.Object === Object && self;\n\n/** Used as a reference to the global object. */\nvar root = freeGlobal || freeSelf || Function('return this')();\n\nmodule.exports = root;\n","var root = require('./_root');\n\n/** Built-in value references. */\nvar Symbol = root.Symbol;\n\nmodule.exports = Symbol;\n","var Symbol = require('./_Symbol');\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/** Built-in value references. */\nvar symToStringTag = Symbol ? Symbol.toStringTag : undefined;\n\n/**\n * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the raw `toStringTag`.\n */\nfunction getRawTag(value) {\n var isOwn = hasOwnProperty.call(value, symToStringTag),\n tag = value[symToStringTag];\n\n try {\n value[symToStringTag] = undefined;\n var unmasked = true;\n } catch (e) {}\n\n var result = nativeObjectToString.call(value);\n if (unmasked) {\n if (isOwn) {\n value[symToStringTag] = tag;\n } else {\n delete value[symToStringTag];\n }\n }\n return result;\n}\n\nmodule.exports = getRawTag;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\nfunction objectToString(value) {\n return nativeObjectToString.call(value);\n}\n\nmodule.exports = objectToString;\n","var Symbol = require('./_Symbol'),\n getRawTag = require('./_getRawTag'),\n objectToString = require('./_objectToString');\n\n/** `Object#toString` result references. */\nvar nullTag = '[object Null]',\n undefinedTag = '[object Undefined]';\n\n/** Built-in value references. */\nvar symToStringTag = Symbol ? Symbol.toStringTag : undefined;\n\n/**\n * The base implementation of `getTag` without fallbacks for buggy environments.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the `toStringTag`.\n */\nfunction baseGetTag(value) {\n if (value == null) {\n return value === undefined ? undefinedTag : nullTag;\n }\n return (symToStringTag && symToStringTag in Object(value))\n ? getRawTag(value)\n : objectToString(value);\n}\n\nmodule.exports = baseGetTag;\n","/**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\nfunction isObject(value) {\n var type = typeof value;\n return value != null && (type == 'object' || type == 'function');\n}\n\nmodule.exports = isObject;\n","var baseGetTag = require('./_baseGetTag'),\n isObject = require('./isObject');\n\n/** `Object#toString` result references. */\nvar asyncTag = '[object AsyncFunction]',\n funcTag = '[object Function]',\n genTag = '[object GeneratorFunction]',\n proxyTag = '[object Proxy]';\n\n/**\n * Checks if `value` is classified as a `Function` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a function, else `false`.\n * @example\n *\n * _.isFunction(_);\n * // => true\n *\n * _.isFunction(/abc/);\n * // => false\n */\nfunction isFunction(value) {\n if (!isObject(value)) {\n return false;\n }\n // The use of `Object#toString` avoids issues with the `typeof` operator\n // in Safari 9 which returns 'object' for typed arrays and other constructors.\n var tag = baseGetTag(value);\n return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;\n}\n\nmodule.exports = isFunction;\n","var coreJsData = require('./_coreJsData');\n\n/** Used to detect methods masquerading as native. */\nvar maskSrcKey = (function() {\n var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');\n return uid ? ('Symbol(src)_1.' + uid) : '';\n}());\n\n/**\n * Checks if `func` has its source masked.\n *\n * @private\n * @param {Function} func The function to check.\n * @returns {boolean} Returns `true` if `func` is masked, else `false`.\n */\nfunction isMasked(func) {\n return !!maskSrcKey && (maskSrcKey in func);\n}\n\nmodule.exports = isMasked;\n","var root = require('./_root');\n\n/** Used to detect overreaching core-js shims. */\nvar coreJsData = root['__core-js_shared__'];\n\nmodule.exports = coreJsData;\n","/** Used for built-in method references. */\nvar funcProto = Function.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/**\n * Converts `func` to its source code.\n *\n * @private\n * @param {Function} func The function to convert.\n * @returns {string} Returns the source code.\n */\nfunction toSource(func) {\n if (func != null) {\n try {\n return funcToString.call(func);\n } catch (e) {}\n try {\n return (func + '');\n } catch (e) {}\n }\n return '';\n}\n\nmodule.exports = toSource;\n","var isFunction = require('./isFunction'),\n isMasked = require('./_isMasked'),\n isObject = require('./isObject'),\n toSource = require('./_toSource');\n\n/**\n * Used to match `RegExp`\n * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).\n */\nvar reRegExpChar = /[\\\\^$.*+?()[\\]{}|]/g;\n\n/** Used to detect host constructors (Safari). */\nvar reIsHostCtor = /^\\[object .+?Constructor\\]$/;\n\n/** Used for built-in method references. */\nvar funcProto = Function.prototype,\n objectProto = Object.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Used to detect if a method is native. */\nvar reIsNative = RegExp('^' +\n funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\\\$&')\n .replace(/hasOwnProperty|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g, '$1.*?') + '$'\n);\n\n/**\n * The base implementation of `_.isNative` without bad shim checks.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a native function,\n * else `false`.\n */\nfunction baseIsNative(value) {\n if (!isObject(value) || isMasked(value)) {\n return false;\n }\n var pattern = isFunction(value) ? reIsNative : reIsHostCtor;\n return pattern.test(toSource(value));\n}\n\nmodule.exports = baseIsNative;\n","/**\n * Gets the value at `key` of `object`.\n *\n * @private\n * @param {Object} [object] The object to query.\n * @param {string} key The key of the property to get.\n * @returns {*} Returns the property value.\n */\nfunction getValue(object, key) {\n return object == null ? undefined : object[key];\n}\n\nmodule.exports = getValue;\n","var baseIsNative = require('./_baseIsNative'),\n getValue = require('./_getValue');\n\n/**\n * Gets the native function at `key` of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {string} key The key of the method to get.\n * @returns {*} Returns the function if it's native, else `undefined`.\n */\nfunction getNative(object, key) {\n var value = getValue(object, key);\n return baseIsNative(value) ? value : undefined;\n}\n\nmodule.exports = getNative;\n","var getNative = require('./_getNative');\n\nvar defineProperty = (function() {\n try {\n var func = getNative(Object, 'defineProperty');\n func({}, '', {});\n return func;\n } catch (e) {}\n}());\n\nmodule.exports = defineProperty;\n","var constant = require('./constant'),\n defineProperty = require('./_defineProperty'),\n identity = require('./identity');\n\n/**\n * The base implementation of `setToString` without support for hot loop shorting.\n *\n * @private\n * @param {Function} func The function to modify.\n * @param {Function} string The `toString` result.\n * @returns {Function} Returns `func`.\n */\nvar baseSetToString = !defineProperty ? identity : function(func, string) {\n return defineProperty(func, 'toString', {\n 'configurable': true,\n 'enumerable': false,\n 'value': constant(string),\n 'writable': true\n });\n};\n\nmodule.exports = baseSetToString;\n","/** Used to detect hot functions by number of calls within a span of milliseconds. */\nvar HOT_COUNT = 800,\n HOT_SPAN = 16;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeNow = Date.now;\n\n/**\n * Creates a function that'll short out and invoke `identity` instead\n * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`\n * milliseconds.\n *\n * @private\n * @param {Function} func The function to restrict.\n * @returns {Function} Returns the new shortable function.\n */\nfunction shortOut(func) {\n var count = 0,\n lastCalled = 0;\n\n return function() {\n var stamp = nativeNow(),\n remaining = HOT_SPAN - (stamp - lastCalled);\n\n lastCalled = stamp;\n if (remaining > 0) {\n if (++count >= HOT_COUNT) {\n return arguments[0];\n }\n } else {\n count = 0;\n }\n return func.apply(undefined, arguments);\n };\n}\n\nmodule.exports = shortOut;\n","var baseSetToString = require('./_baseSetToString'),\n shortOut = require('./_shortOut');\n\n/**\n * Sets the `toString` method of `func` to return `string`.\n *\n * @private\n * @param {Function} func The function to modify.\n * @param {Function} string The `toString` result.\n * @returns {Function} Returns `func`.\n */\nvar setToString = shortOut(baseSetToString);\n\nmodule.exports = setToString;\n","var identity = require('./identity'),\n overRest = require('./_overRest'),\n setToString = require('./_setToString');\n\n/**\n * The base implementation of `_.rest` which doesn't validate or coerce arguments.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @returns {Function} Returns the new function.\n */\nfunction baseRest(func, start) {\n return setToString(overRest(func, start, identity), func + '');\n}\n\nmodule.exports = baseRest;\n","/** Used to match a single whitespace character. */\nvar reWhitespace = /\\s/;\n\n/**\n * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace\n * character of `string`.\n *\n * @private\n * @param {string} string The string to inspect.\n * @returns {number} Returns the index of the last non-whitespace character.\n */\nfunction trimmedEndIndex(string) {\n var index = string.length;\n\n while (index-- && reWhitespace.test(string.charAt(index))) {}\n return index;\n}\n\nmodule.exports = trimmedEndIndex;\n","var trimmedEndIndex = require('./_trimmedEndIndex');\n\n/** Used to match leading whitespace. */\nvar reTrimStart = /^\\s+/;\n\n/**\n * The base implementation of `_.trim`.\n *\n * @private\n * @param {string} string The string to trim.\n * @returns {string} Returns the trimmed string.\n */\nfunction baseTrim(string) {\n return string\n ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '')\n : string;\n}\n\nmodule.exports = baseTrim;\n","/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return value != null && typeof value == 'object';\n}\n\nmodule.exports = isObjectLike;\n","var baseGetTag = require('./_baseGetTag'),\n isObjectLike = require('./isObjectLike');\n\n/** `Object#toString` result references. */\nvar symbolTag = '[object Symbol]';\n\n/**\n * Checks if `value` is classified as a `Symbol` primitive or object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.\n * @example\n *\n * _.isSymbol(Symbol.iterator);\n * // => true\n *\n * _.isSymbol('abc');\n * // => false\n */\nfunction isSymbol(value) {\n return typeof value == 'symbol' ||\n (isObjectLike(value) && baseGetTag(value) == symbolTag);\n}\n\nmodule.exports = isSymbol;\n","var baseTrim = require('./_baseTrim'),\n isObject = require('./isObject'),\n isSymbol = require('./isSymbol');\n\n/** Used as references for various `Number` constants. */\nvar NAN = 0 / 0;\n\n/** Used to detect bad signed hexadecimal string values. */\nvar reIsBadHex = /^[-+]0x[0-9a-f]+$/i;\n\n/** Used to detect binary string values. */\nvar reIsBinary = /^0b[01]+$/i;\n\n/** Used to detect octal string values. */\nvar reIsOctal = /^0o[0-7]+$/i;\n\n/** Built-in method references without a dependency on `root`. */\nvar freeParseInt = parseInt;\n\n/**\n * Converts `value` to a number.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to process.\n * @returns {number} Returns the number.\n * @example\n *\n * _.toNumber(3.2);\n * // => 3.2\n *\n * _.toNumber(Number.MIN_VALUE);\n * // => 5e-324\n *\n * _.toNumber(Infinity);\n * // => Infinity\n *\n * _.toNumber('3.2');\n * // => 3.2\n */\nfunction toNumber(value) {\n if (typeof value == 'number') {\n return value;\n }\n if (isSymbol(value)) {\n return NAN;\n }\n if (isObject(value)) {\n var other = typeof value.valueOf == 'function' ? value.valueOf() : value;\n value = isObject(other) ? (other + '') : other;\n }\n if (typeof value != 'string') {\n return value === 0 ? value : +value;\n }\n value = baseTrim(value);\n var isBinary = reIsBinary.test(value);\n return (isBinary || reIsOctal.test(value))\n ? freeParseInt(value.slice(2), isBinary ? 2 : 8)\n : (reIsBadHex.test(value) ? NAN : +value);\n}\n\nmodule.exports = toNumber;\n","var baseDelay = require('./_baseDelay'),\n baseRest = require('./_baseRest'),\n toNumber = require('./toNumber');\n\n/**\n * Invokes `func` after `wait` milliseconds. Any additional arguments are\n * provided to `func` when it's invoked.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to delay.\n * @param {number} wait The number of milliseconds to delay invocation.\n * @param {...*} [args] The arguments to invoke `func` with.\n * @returns {number} Returns the timer id.\n * @example\n *\n * _.delay(function(text) {\n * console.log(text);\n * }, 1000, 'later');\n * // => Logs 'later' after one second.\n */\nvar delay = baseRest(function(func, wait, args) {\n return baseDelay(func, toNumber(wait) || 0, args);\n});\n\nmodule.exports = delay;\n","/*\n * Copyright 2021 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the 'License');\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an 'AS IS' BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n(function () {\n \"use strict\";\n\n const delay = require(\"lodash/delay\");\n\n addCodeToolElements();\n\n function addCodeToolElements() {\n for (const preElement of document.querySelectorAll(\".doc pre.highlight\")) {\n const codeToolsElement = document.createElement(\"div\");\n codeToolsElement.className = \"codetools\";\n if (addButtons(preElement, codeToolsElement)) {\n preElement.appendChild(codeToolsElement);\n }\n }\n\n function addButtons(preElement, codeToolsElement) {\n let numberOfButtons = 0;\n if (hasHideWhenFoldedSpans(preElement)) {\n addFoldUnfoldButton(preElement, codeToolsElement);\n numberOfButtons++;\n }\n if (window.navigator.clipboard) {\n addCopyButton(preElement, codeToolsElement);\n numberOfButtons++;\n }\n return numberOfButtons > 0;\n }\n\n function hasHideWhenFoldedSpans(preElement) {\n return !!preElement.querySelector(\"span.hide-when-folded\");\n }\n\n function addFoldUnfoldButton(preElement, codeToolsElement) {\n const foldUnfoldButton = createButton();\n updateFoldUnfoldButton(foldUnfoldButton, true);\n foldUnfoldButton.addEventListener(\n \"click\",\n onFoldUnfoldButtonClick.bind(foldUnfoldButton, preElement)\n );\n codeToolsElement.appendChild(foldUnfoldButton);\n }\n\n function addCopyButton(preElement, codeToolsElement) {\n const copyButton = createButton(\"Copy to clipboard\", \"copy-button\");\n copyButton.addEventListener(\n \"click\",\n onCopyButtonClick.bind(copyButton, preElement)\n );\n copyButton.addEventListener(\"mouseleave\", clearClicked.bind(copyButton));\n copyButton.addEventListener(\"blur\", clearClicked.bind(copyButton));\n const copiedPopup = document.createElement(\"span\");\n copyButton.appendChild(copiedPopup);\n copiedPopup.className = \"copied\";\n codeToolsElement.appendChild(copyButton);\n }\n\n function createButton(label, className) {\n const buttonElement = document.createElement(\"button\");\n buttonElement.className = className;\n buttonElement.title = label;\n buttonElement.type = \"button\";\n const labelElement = document.createElement(\"span\");\n labelElement.appendChild(document.createTextNode(label));\n labelElement.className = \"label\";\n buttonElement.appendChild(labelElement);\n return buttonElement;\n }\n }\n\n function onCopyButtonClick(preElement) {\n const codeElement = preElement.querySelector(\"code\");\n const copy = codeElement.cloneNode(true);\n for (const hideWhenFoldedElement of copy.querySelectorAll(\n \".hide-when-unfolded\"\n )) {\n hideWhenFoldedElement.parentNode.removeChild(hideWhenFoldedElement);\n }\n const text = copy.innerText;\n if (text) {\n window.navigator.clipboard\n .writeText(text + \"\\n\")\n .then(markClicked.bind(this));\n }\n }\n\n function markClicked() {\n this.classList.add(\"clicked\");\n }\n\n function clearClicked() {\n this.classList.remove(\"clicked\");\n }\n\n function onFoldUnfoldButtonClick(preElement) {\n const codeElement = preElement.querySelector(\"code\");\n const unfolding = !codeElement.classList.contains(\"unfolded\");\n codeElement.classList.remove(unfolding ? \"folding\" : \"unfolding\");\n codeElement.classList.add(unfolding ? \"unfolding\" : \"folding\");\n delay(function () {\n codeElement.classList.remove(unfolding ? \"unfolding\" : \"folding\");\n codeElement.classList.toggle(\"unfolded\");\n }, 1100);\n updateFoldUnfoldButton(this, !unfolding);\n }\n\n function updateFoldUnfoldButton(button, unfold) {\n const label = unfold ? \"Expand folded text\" : \"Collapse foldable text\";\n button.classList.remove(unfold ? \"fold-button\" : \"unfold-button\");\n button.classList.add(unfold ? \"unfold-button\" : \"fold-button\");\n button.querySelector(\"span.label\").innerText = label;\n button.title = label;\n }\n})();\n","\n}());","function deepFreeze(obj) {\n if (obj instanceof Map) {\n obj.clear = obj.delete = obj.set = function () {\n throw new Error('map is read-only');\n };\n } else if (obj instanceof Set) {\n obj.add = obj.clear = obj.delete = function () {\n throw new Error('set is read-only');\n };\n }\n\n // Freeze self\n Object.freeze(obj);\n\n Object.getOwnPropertyNames(obj).forEach(function (name) {\n var prop = obj[name];\n\n // Freeze prop if it is an object\n if (typeof prop == 'object' && !Object.isFrozen(prop)) {\n deepFreeze(prop);\n }\n });\n\n return obj;\n}\n\nvar deepFreezeEs6 = deepFreeze;\nvar _default = deepFreeze;\ndeepFreezeEs6.default = _default;\n\n/** @implements CallbackResponse */\nclass Response {\n /**\n * @param {CompiledMode} mode\n */\n constructor(mode) {\n // eslint-disable-next-line no-undefined\n if (mode.data === undefined) mode.data = {};\n\n this.data = mode.data;\n this.isMatchIgnored = false;\n }\n\n ignoreMatch() {\n this.isMatchIgnored = true;\n }\n}\n\n/**\n * @param {string} value\n * @returns {string}\n */\nfunction escapeHTML(value) {\n return value\n .replace(/&/g, '&')\n .replace(//g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\n/**\n * performs a shallow merge of multiple objects into one\n *\n * @template T\n * @param {T} original\n * @param {Record[]} objects\n * @returns {T} a single new object\n */\nfunction inherit(original, ...objects) {\n /** @type Record */\n const result = Object.create(null);\n\n for (const key in original) {\n result[key] = original[key];\n }\n objects.forEach(function(obj) {\n for (const key in obj) {\n result[key] = obj[key];\n }\n });\n return /** @type {T} */ (result);\n}\n\n/**\n * @typedef {object} Renderer\n * @property {(text: string) => void} addText\n * @property {(node: Node) => void} openNode\n * @property {(node: Node) => void} closeNode\n * @property {() => string} value\n */\n\n/** @typedef {{kind?: string, sublanguage?: boolean}} Node */\n/** @typedef {{walk: (r: Renderer) => void}} Tree */\n/** */\n\nconst SPAN_CLOSE = '
      ';\n\n/**\n * Determines if a node needs to be wrapped in \n *\n * @param {Node} node */\nconst emitsWrappingTags = (node) => {\n return !!node.kind;\n};\n\n/** @type {Renderer} */\nclass HTMLRenderer {\n /**\n * Creates a new HTMLRenderer\n *\n * @param {Tree} parseTree - the parse tree (must support `walk` API)\n * @param {{classPrefix: string}} options\n */\n constructor(parseTree, options) {\n this.buffer = \"\";\n this.classPrefix = options.classPrefix;\n parseTree.walk(this);\n }\n\n /**\n * Adds texts to the output stream\n *\n * @param {string} text */\n addText(text) {\n this.buffer += escapeHTML(text);\n }\n\n /**\n * Adds a node open to the output stream (if needed)\n *\n * @param {Node} node */\n openNode(node) {\n if (!emitsWrappingTags(node)) return;\n\n let className = node.kind;\n if (!node.sublanguage) {\n className = `${this.classPrefix}${className}`;\n }\n this.span(className);\n }\n\n /**\n * Adds a node close to the output stream (if needed)\n *\n * @param {Node} node */\n closeNode(node) {\n if (!emitsWrappingTags(node)) return;\n\n this.buffer += SPAN_CLOSE;\n }\n\n /**\n * returns the accumulated buffer\n */\n value() {\n return this.buffer;\n }\n\n // helpers\n\n /**\n * Builds a span element\n *\n * @param {string} className */\n span(className) {\n this.buffer += ``;\n }\n}\n\n/** @typedef {{kind?: string, sublanguage?: boolean, children: Node[]} | string} Node */\n/** @typedef {{kind?: string, sublanguage?: boolean, children: Node[]} } DataNode */\n/** */\n\nclass TokenTree {\n constructor() {\n /** @type DataNode */\n this.rootNode = { children: [] };\n this.stack = [this.rootNode];\n }\n\n get top() {\n return this.stack[this.stack.length - 1];\n }\n\n get root() { return this.rootNode; }\n\n /** @param {Node} node */\n add(node) {\n this.top.children.push(node);\n }\n\n /** @param {string} kind */\n openNode(kind) {\n /** @type Node */\n const node = { kind, children: [] };\n this.add(node);\n this.stack.push(node);\n }\n\n closeNode() {\n if (this.stack.length > 1) {\n return this.stack.pop();\n }\n // eslint-disable-next-line no-undefined\n return undefined;\n }\n\n closeAllNodes() {\n while (this.closeNode());\n }\n\n toJSON() {\n return JSON.stringify(this.rootNode, null, 4);\n }\n\n /**\n * @typedef { import(\"./html_renderer\").Renderer } Renderer\n * @param {Renderer} builder\n */\n walk(builder) {\n // this does not\n return this.constructor._walk(builder, this.rootNode);\n // this works\n // return TokenTree._walk(builder, this.rootNode);\n }\n\n /**\n * @param {Renderer} builder\n * @param {Node} node\n */\n static _walk(builder, node) {\n if (typeof node === \"string\") {\n builder.addText(node);\n } else if (node.children) {\n builder.openNode(node);\n node.children.forEach((child) => this._walk(builder, child));\n builder.closeNode(node);\n }\n return builder;\n }\n\n /**\n * @param {Node} node\n */\n static _collapse(node) {\n if (typeof node === \"string\") return;\n if (!node.children) return;\n\n if (node.children.every(el => typeof el === \"string\")) {\n // node.text = node.children.join(\"\");\n // delete node.children;\n node.children = [node.children.join(\"\")];\n } else {\n node.children.forEach((child) => {\n TokenTree._collapse(child);\n });\n }\n }\n}\n\n/**\n Currently this is all private API, but this is the minimal API necessary\n that an Emitter must implement to fully support the parser.\n\n Minimal interface:\n\n - addKeyword(text, kind)\n - addText(text)\n - addSublanguage(emitter, subLanguageName)\n - finalize()\n - openNode(kind)\n - closeNode()\n - closeAllNodes()\n - toHTML()\n\n*/\n\n/**\n * @implements {Emitter}\n */\nclass TokenTreeEmitter extends TokenTree {\n /**\n * @param {*} options\n */\n constructor(options) {\n super();\n this.options = options;\n }\n\n /**\n * @param {string} text\n * @param {string} kind\n */\n addKeyword(text, kind) {\n if (text === \"\") { return; }\n\n this.openNode(kind);\n this.addText(text);\n this.closeNode();\n }\n\n /**\n * @param {string} text\n */\n addText(text) {\n if (text === \"\") { return; }\n\n this.add(text);\n }\n\n /**\n * @param {Emitter & {root: DataNode}} emitter\n * @param {string} name\n */\n addSublanguage(emitter, name) {\n /** @type DataNode */\n const node = emitter.root;\n node.kind = name;\n node.sublanguage = true;\n this.add(node);\n }\n\n toHTML() {\n const renderer = new HTMLRenderer(this, this.options);\n return renderer.value();\n }\n\n finalize() {\n return true;\n }\n}\n\n/**\n * @param {string} value\n * @returns {RegExp}\n * */\nfunction escape(value) {\n return new RegExp(value.replace(/[-/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&'), 'm');\n}\n\n/**\n * @param {RegExp | string } re\n * @returns {string}\n */\nfunction source(re) {\n if (!re) return null;\n if (typeof re === \"string\") return re;\n\n return re.source;\n}\n\n/**\n * @param {...(RegExp | string) } args\n * @returns {string}\n */\nfunction concat(...args) {\n const joined = args.map((x) => source(x)).join(\"\");\n return joined;\n}\n\n/**\n * Any of the passed expresssions may match\n *\n * Creates a huge this | this | that | that match\n * @param {(RegExp | string)[] } args\n * @returns {string}\n */\nfunction either(...args) {\n const joined = '(' + args.map((x) => source(x)).join(\"|\") + \")\";\n return joined;\n}\n\n/**\n * @param {RegExp} re\n * @returns {number}\n */\nfunction countMatchGroups(re) {\n return (new RegExp(re.toString() + '|')).exec('').length - 1;\n}\n\n/**\n * Does lexeme start with a regular expression match at the beginning\n * @param {RegExp} re\n * @param {string} lexeme\n */\nfunction startsWith(re, lexeme) {\n const match = re && re.exec(lexeme);\n return match && match.index === 0;\n}\n\n// BACKREF_RE matches an open parenthesis or backreference. To avoid\n// an incorrect parse, it additionally matches the following:\n// - [...] elements, where the meaning of parentheses and escapes change\n// - other escape sequences, so we do not misparse escape sequences as\n// interesting elements\n// - non-matching or lookahead parentheses, which do not capture. These\n// follow the '(' with a '?'.\nconst BACKREF_RE = /\\[(?:[^\\\\\\]]|\\\\.)*\\]|\\(\\??|\\\\([1-9][0-9]*)|\\\\./;\n\n// join logically computes regexps.join(separator), but fixes the\n// backreferences so they continue to match.\n// it also places each individual regular expression into it's own\n// match group, keeping track of the sequencing of those match groups\n// is currently an exercise for the caller. :-)\n/**\n * @param {(string | RegExp)[]} regexps\n * @param {string} separator\n * @returns {string}\n */\nfunction join(regexps, separator = \"|\") {\n let numCaptures = 0;\n\n return regexps.map((regex) => {\n numCaptures += 1;\n const offset = numCaptures;\n let re = source(regex);\n let out = '';\n\n while (re.length > 0) {\n const match = BACKREF_RE.exec(re);\n if (!match) {\n out += re;\n break;\n }\n out += re.substring(0, match.index);\n re = re.substring(match.index + match[0].length);\n if (match[0][0] === '\\\\' && match[1]) {\n // Adjust the backreference.\n out += '\\\\' + String(Number(match[1]) + offset);\n } else {\n out += match[0];\n if (match[0] === '(') {\n numCaptures++;\n }\n }\n }\n return out;\n }).map(re => `(${re})`).join(separator);\n}\n\n// Common regexps\nconst MATCH_NOTHING_RE = /\\b\\B/;\nconst IDENT_RE = '[a-zA-Z]\\\\w*';\nconst UNDERSCORE_IDENT_RE = '[a-zA-Z_]\\\\w*';\nconst NUMBER_RE = '\\\\b\\\\d+(\\\\.\\\\d+)?';\nconst C_NUMBER_RE = '(-?)(\\\\b0[xX][a-fA-F0-9]+|(\\\\b\\\\d+(\\\\.\\\\d*)?|\\\\.\\\\d+)([eE][-+]?\\\\d+)?)'; // 0x..., 0..., decimal, float\nconst BINARY_NUMBER_RE = '\\\\b(0b[01]+)'; // 0b...\nconst RE_STARTERS_RE = '!|!=|!==|%|%=|&|&&|&=|\\\\*|\\\\*=|\\\\+|\\\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\\\?|\\\\[|\\\\{|\\\\(|\\\\^|\\\\^=|\\\\||\\\\|=|\\\\|\\\\||~';\n\n/**\n* @param { Partial & {binary?: string | RegExp} } opts\n*/\nconst SHEBANG = (opts = {}) => {\n const beginShebang = /^#![ ]*\\//;\n if (opts.binary) {\n opts.begin = concat(\n beginShebang,\n /.*\\b/,\n opts.binary,\n /\\b.*/);\n }\n return inherit({\n className: 'meta',\n begin: beginShebang,\n end: /$/,\n relevance: 0,\n /** @type {ModeCallback} */\n \"on:begin\": (m, resp) => {\n if (m.index !== 0) resp.ignoreMatch();\n }\n }, opts);\n};\n\n// Common modes\nconst BACKSLASH_ESCAPE = {\n begin: '\\\\\\\\[\\\\s\\\\S]', relevance: 0\n};\nconst APOS_STRING_MODE = {\n className: 'string',\n begin: '\\'',\n end: '\\'',\n illegal: '\\\\n',\n contains: [BACKSLASH_ESCAPE]\n};\nconst QUOTE_STRING_MODE = {\n className: 'string',\n begin: '\"',\n end: '\"',\n illegal: '\\\\n',\n contains: [BACKSLASH_ESCAPE]\n};\nconst PHRASAL_WORDS_MODE = {\n begin: /\\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\\b/\n};\n/**\n * Creates a comment mode\n *\n * @param {string | RegExp} begin\n * @param {string | RegExp} end\n * @param {Mode | {}} [modeOptions]\n * @returns {Partial}\n */\nconst COMMENT = function(begin, end, modeOptions = {}) {\n const mode = inherit(\n {\n className: 'comment',\n begin,\n end,\n contains: []\n },\n modeOptions\n );\n mode.contains.push(PHRASAL_WORDS_MODE);\n mode.contains.push({\n className: 'doctag',\n begin: '(?:TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):',\n relevance: 0\n });\n return mode;\n};\nconst C_LINE_COMMENT_MODE = COMMENT('//', '$');\nconst C_BLOCK_COMMENT_MODE = COMMENT('/\\\\*', '\\\\*/');\nconst HASH_COMMENT_MODE = COMMENT('#', '$');\nconst NUMBER_MODE = {\n className: 'number',\n begin: NUMBER_RE,\n relevance: 0\n};\nconst C_NUMBER_MODE = {\n className: 'number',\n begin: C_NUMBER_RE,\n relevance: 0\n};\nconst BINARY_NUMBER_MODE = {\n className: 'number',\n begin: BINARY_NUMBER_RE,\n relevance: 0\n};\nconst CSS_NUMBER_MODE = {\n className: 'number',\n begin: NUMBER_RE + '(' +\n '%|em|ex|ch|rem' +\n '|vw|vh|vmin|vmax' +\n '|cm|mm|in|pt|pc|px' +\n '|deg|grad|rad|turn' +\n '|s|ms' +\n '|Hz|kHz' +\n '|dpi|dpcm|dppx' +\n ')?',\n relevance: 0\n};\nconst REGEXP_MODE = {\n // this outer rule makes sure we actually have a WHOLE regex and not simply\n // an expression such as:\n //\n // 3 / something\n //\n // (which will then blow up when regex's `illegal` sees the newline)\n begin: /(?=\\/[^/\\n]*\\/)/,\n contains: [{\n className: 'regexp',\n begin: /\\//,\n end: /\\/[gimuy]*/,\n illegal: /\\n/,\n contains: [\n BACKSLASH_ESCAPE,\n {\n begin: /\\[/,\n end: /\\]/,\n relevance: 0,\n contains: [BACKSLASH_ESCAPE]\n }\n ]\n }]\n};\nconst TITLE_MODE = {\n className: 'title',\n begin: IDENT_RE,\n relevance: 0\n};\nconst UNDERSCORE_TITLE_MODE = {\n className: 'title',\n begin: UNDERSCORE_IDENT_RE,\n relevance: 0\n};\nconst METHOD_GUARD = {\n // excludes method names from keyword processing\n begin: '\\\\.\\\\s*' + UNDERSCORE_IDENT_RE,\n relevance: 0\n};\n\n/**\n * Adds end same as begin mechanics to a mode\n *\n * Your mode must include at least a single () match group as that first match\n * group is what is used for comparison\n * @param {Partial} mode\n */\nconst END_SAME_AS_BEGIN = function(mode) {\n return Object.assign(mode,\n {\n /** @type {ModeCallback} */\n 'on:begin': (m, resp) => { resp.data._beginMatch = m[1]; },\n /** @type {ModeCallback} */\n 'on:end': (m, resp) => { if (resp.data._beginMatch !== m[1]) resp.ignoreMatch(); }\n });\n};\n\nvar MODES = /*#__PURE__*/Object.freeze({\n __proto__: null,\n MATCH_NOTHING_RE: MATCH_NOTHING_RE,\n IDENT_RE: IDENT_RE,\n UNDERSCORE_IDENT_RE: UNDERSCORE_IDENT_RE,\n NUMBER_RE: NUMBER_RE,\n C_NUMBER_RE: C_NUMBER_RE,\n BINARY_NUMBER_RE: BINARY_NUMBER_RE,\n RE_STARTERS_RE: RE_STARTERS_RE,\n SHEBANG: SHEBANG,\n BACKSLASH_ESCAPE: BACKSLASH_ESCAPE,\n APOS_STRING_MODE: APOS_STRING_MODE,\n QUOTE_STRING_MODE: QUOTE_STRING_MODE,\n PHRASAL_WORDS_MODE: PHRASAL_WORDS_MODE,\n COMMENT: COMMENT,\n C_LINE_COMMENT_MODE: C_LINE_COMMENT_MODE,\n C_BLOCK_COMMENT_MODE: C_BLOCK_COMMENT_MODE,\n HASH_COMMENT_MODE: HASH_COMMENT_MODE,\n NUMBER_MODE: NUMBER_MODE,\n C_NUMBER_MODE: C_NUMBER_MODE,\n BINARY_NUMBER_MODE: BINARY_NUMBER_MODE,\n CSS_NUMBER_MODE: CSS_NUMBER_MODE,\n REGEXP_MODE: REGEXP_MODE,\n TITLE_MODE: TITLE_MODE,\n UNDERSCORE_TITLE_MODE: UNDERSCORE_TITLE_MODE,\n METHOD_GUARD: METHOD_GUARD,\n END_SAME_AS_BEGIN: END_SAME_AS_BEGIN\n});\n\n// Grammar extensions / plugins\n// See: https://github.com/highlightjs/highlight.js/issues/2833\n\n// Grammar extensions allow \"syntactic sugar\" to be added to the grammar modes\n// without requiring any underlying changes to the compiler internals.\n\n// `compileMatch` being the perfect small example of now allowing a grammar\n// author to write `match` when they desire to match a single expression rather\n// than being forced to use `begin`. The extension then just moves `match` into\n// `begin` when it runs. Ie, no features have been added, but we've just made\n// the experience of writing (and reading grammars) a little bit nicer.\n\n// ------\n\n// TODO: We need negative look-behind support to do this properly\n/**\n * Skip a match if it has a preceding dot\n *\n * This is used for `beginKeywords` to prevent matching expressions such as\n * `bob.keyword.do()`. The mode compiler automatically wires this up as a\n * special _internal_ 'on:begin' callback for modes with `beginKeywords`\n * @param {RegExpMatchArray} match\n * @param {CallbackResponse} response\n */\nfunction skipIfhasPrecedingDot(match, response) {\n const before = match.input[match.index - 1];\n if (before === \".\") {\n response.ignoreMatch();\n }\n}\n\n\n/**\n * `beginKeywords` syntactic sugar\n * @type {CompilerExt}\n */\nfunction beginKeywords(mode, parent) {\n if (!parent) return;\n if (!mode.beginKeywords) return;\n\n // for languages with keywords that include non-word characters checking for\n // a word boundary is not sufficient, so instead we check for a word boundary\n // or whitespace - this does no harm in any case since our keyword engine\n // doesn't allow spaces in keywords anyways and we still check for the boundary\n // first\n mode.begin = '\\\\b(' + mode.beginKeywords.split(' ').join('|') + ')(?!\\\\.)(?=\\\\b|\\\\s)';\n mode.__beforeBegin = skipIfhasPrecedingDot;\n mode.keywords = mode.keywords || mode.beginKeywords;\n delete mode.beginKeywords;\n\n // prevents double relevance, the keywords themselves provide\n // relevance, the mode doesn't need to double it\n // eslint-disable-next-line no-undefined\n if (mode.relevance === undefined) mode.relevance = 0;\n}\n\n/**\n * Allow `illegal` to contain an array of illegal values\n * @type {CompilerExt}\n */\nfunction compileIllegal(mode, _parent) {\n if (!Array.isArray(mode.illegal)) return;\n\n mode.illegal = either(...mode.illegal);\n}\n\n/**\n * `match` to match a single expression for readability\n * @type {CompilerExt}\n */\nfunction compileMatch(mode, _parent) {\n if (!mode.match) return;\n if (mode.begin || mode.end) throw new Error(\"begin & end are not supported with match\");\n\n mode.begin = mode.match;\n delete mode.match;\n}\n\n/**\n * provides the default 1 relevance to all modes\n * @type {CompilerExt}\n */\nfunction compileRelevance(mode, _parent) {\n // eslint-disable-next-line no-undefined\n if (mode.relevance === undefined) mode.relevance = 1;\n}\n\n// keywords that should have no default relevance value\nconst COMMON_KEYWORDS = [\n 'of',\n 'and',\n 'for',\n 'in',\n 'not',\n 'or',\n 'if',\n 'then',\n 'parent', // common variable name\n 'list', // common variable name\n 'value' // common variable name\n];\n\nconst DEFAULT_KEYWORD_CLASSNAME = \"keyword\";\n\n/**\n * Given raw keywords from a language definition, compile them.\n *\n * @param {string | Record | Array} rawKeywords\n * @param {boolean} caseInsensitive\n */\nfunction compileKeywords(rawKeywords, caseInsensitive, className = DEFAULT_KEYWORD_CLASSNAME) {\n /** @type KeywordDict */\n const compiledKeywords = {};\n\n // input can be a string of keywords, an array of keywords, or a object with\n // named keys representing className (which can then point to a string or array)\n if (typeof rawKeywords === 'string') {\n compileList(className, rawKeywords.split(\" \"));\n } else if (Array.isArray(rawKeywords)) {\n compileList(className, rawKeywords);\n } else {\n Object.keys(rawKeywords).forEach(function(className) {\n // collapse all our objects back into the parent object\n Object.assign(\n compiledKeywords,\n compileKeywords(rawKeywords[className], caseInsensitive, className)\n );\n });\n }\n return compiledKeywords;\n\n // ---\n\n /**\n * Compiles an individual list of keywords\n *\n * Ex: \"for if when while|5\"\n *\n * @param {string} className\n * @param {Array} keywordList\n */\n function compileList(className, keywordList) {\n if (caseInsensitive) {\n keywordList = keywordList.map(x => x.toLowerCase());\n }\n keywordList.forEach(function(keyword) {\n const pair = keyword.split('|');\n compiledKeywords[pair[0]] = [className, scoreForKeyword(pair[0], pair[1])];\n });\n }\n}\n\n/**\n * Returns the proper score for a given keyword\n *\n * Also takes into account comment keywords, which will be scored 0 UNLESS\n * another score has been manually assigned.\n * @param {string} keyword\n * @param {string} [providedScore]\n */\nfunction scoreForKeyword(keyword, providedScore) {\n // manual scores always win over common keywords\n // so you can force a score of 1 if you really insist\n if (providedScore) {\n return Number(providedScore);\n }\n\n return commonKeyword(keyword) ? 0 : 1;\n}\n\n/**\n * Determines if a given keyword is common or not\n *\n * @param {string} keyword */\nfunction commonKeyword(keyword) {\n return COMMON_KEYWORDS.includes(keyword.toLowerCase());\n}\n\n// compilation\n\n/**\n * Compiles a language definition result\n *\n * Given the raw result of a language definition (Language), compiles this so\n * that it is ready for highlighting code.\n * @param {Language} language\n * @param {{plugins: HLJSPlugin[]}} opts\n * @returns {CompiledLanguage}\n */\nfunction compileLanguage(language, { plugins }) {\n /**\n * Builds a regex with the case sensativility of the current language\n *\n * @param {RegExp | string} value\n * @param {boolean} [global]\n */\n function langRe(value, global) {\n return new RegExp(\n source(value),\n 'm' + (language.case_insensitive ? 'i' : '') + (global ? 'g' : '')\n );\n }\n\n /**\n Stores multiple regular expressions and allows you to quickly search for\n them all in a string simultaneously - returning the first match. It does\n this by creating a huge (a|b|c) regex - each individual item wrapped with ()\n and joined by `|` - using match groups to track position. When a match is\n found checking which position in the array has content allows us to figure\n out which of the original regexes / match groups triggered the match.\n\n The match object itself (the result of `Regex.exec`) is returned but also\n enhanced by merging in any meta-data that was registered with the regex.\n This is how we keep track of which mode matched, and what type of rule\n (`illegal`, `begin`, end, etc).\n */\n class MultiRegex {\n constructor() {\n this.matchIndexes = {};\n // @ts-ignore\n this.regexes = [];\n this.matchAt = 1;\n this.position = 0;\n }\n\n // @ts-ignore\n addRule(re, opts) {\n opts.position = this.position++;\n // @ts-ignore\n this.matchIndexes[this.matchAt] = opts;\n this.regexes.push([opts, re]);\n this.matchAt += countMatchGroups(re) + 1;\n }\n\n compile() {\n if (this.regexes.length === 0) {\n // avoids the need to check length every time exec is called\n // @ts-ignore\n this.exec = () => null;\n }\n const terminators = this.regexes.map(el => el[1]);\n this.matcherRe = langRe(join(terminators), true);\n this.lastIndex = 0;\n }\n\n /** @param {string} s */\n exec(s) {\n this.matcherRe.lastIndex = this.lastIndex;\n const match = this.matcherRe.exec(s);\n if (!match) { return null; }\n\n // eslint-disable-next-line no-undefined\n const i = match.findIndex((el, i) => i > 0 && el !== undefined);\n // @ts-ignore\n const matchData = this.matchIndexes[i];\n // trim off any earlier non-relevant match groups (ie, the other regex\n // match groups that make up the multi-matcher)\n match.splice(0, i);\n\n return Object.assign(match, matchData);\n }\n }\n\n /*\n Created to solve the key deficiently with MultiRegex - there is no way to\n test for multiple matches at a single location. Why would we need to do\n that? In the future a more dynamic engine will allow certain matches to be\n ignored. An example: if we matched say the 3rd regex in a large group but\n decided to ignore it - we'd need to started testing again at the 4th\n regex... but MultiRegex itself gives us no real way to do that.\n\n So what this class creates MultiRegexs on the fly for whatever search\n position they are needed.\n\n NOTE: These additional MultiRegex objects are created dynamically. For most\n grammars most of the time we will never actually need anything more than the\n first MultiRegex - so this shouldn't have too much overhead.\n\n Say this is our search group, and we match regex3, but wish to ignore it.\n\n regex1 | regex2 | regex3 | regex4 | regex5 ' ie, startAt = 0\n\n What we need is a new MultiRegex that only includes the remaining\n possibilities:\n\n regex4 | regex5 ' ie, startAt = 3\n\n This class wraps all that complexity up in a simple API... `startAt` decides\n where in the array of expressions to start doing the matching. It\n auto-increments, so if a match is found at position 2, then startAt will be\n set to 3. If the end is reached startAt will return to 0.\n\n MOST of the time the parser will be setting startAt manually to 0.\n */\n class ResumableMultiRegex {\n constructor() {\n // @ts-ignore\n this.rules = [];\n // @ts-ignore\n this.multiRegexes = [];\n this.count = 0;\n\n this.lastIndex = 0;\n this.regexIndex = 0;\n }\n\n // @ts-ignore\n getMatcher(index) {\n if (this.multiRegexes[index]) return this.multiRegexes[index];\n\n const matcher = new MultiRegex();\n this.rules.slice(index).forEach(([re, opts]) => matcher.addRule(re, opts));\n matcher.compile();\n this.multiRegexes[index] = matcher;\n return matcher;\n }\n\n resumingScanAtSamePosition() {\n return this.regexIndex !== 0;\n }\n\n considerAll() {\n this.regexIndex = 0;\n }\n\n // @ts-ignore\n addRule(re, opts) {\n this.rules.push([re, opts]);\n if (opts.type === \"begin\") this.count++;\n }\n\n /** @param {string} s */\n exec(s) {\n const m = this.getMatcher(this.regexIndex);\n m.lastIndex = this.lastIndex;\n let result = m.exec(s);\n\n // The following is because we have no easy way to say \"resume scanning at the\n // existing position but also skip the current rule ONLY\". What happens is\n // all prior rules are also skipped which can result in matching the wrong\n // thing. Example of matching \"booger\":\n\n // our matcher is [string, \"booger\", number]\n //\n // ....booger....\n\n // if \"booger\" is ignored then we'd really need a regex to scan from the\n // SAME position for only: [string, number] but ignoring \"booger\" (if it\n // was the first match), a simple resume would scan ahead who knows how\n // far looking only for \"number\", ignoring potential string matches (or\n // future \"booger\" matches that might be valid.)\n\n // So what we do: We execute two matchers, one resuming at the same\n // position, but the second full matcher starting at the position after:\n\n // /--- resume first regex match here (for [number])\n // |/---- full match here for [string, \"booger\", number]\n // vv\n // ....booger....\n\n // Which ever results in a match first is then used. So this 3-4 step\n // process essentially allows us to say \"match at this position, excluding\n // a prior rule that was ignored\".\n //\n // 1. Match \"booger\" first, ignore. Also proves that [string] does non match.\n // 2. Resume matching for [number]\n // 3. Match at index + 1 for [string, \"booger\", number]\n // 4. If #2 and #3 result in matches, which came first?\n if (this.resumingScanAtSamePosition()) {\n if (result && result.index === this.lastIndex) ; else { // use the second matcher result\n const m2 = this.getMatcher(0);\n m2.lastIndex = this.lastIndex + 1;\n result = m2.exec(s);\n }\n }\n\n if (result) {\n this.regexIndex += result.position + 1;\n if (this.regexIndex === this.count) {\n // wrap-around to considering all matches again\n this.considerAll();\n }\n }\n\n return result;\n }\n }\n\n /**\n * Given a mode, builds a huge ResumableMultiRegex that can be used to walk\n * the content and find matches.\n *\n * @param {CompiledMode} mode\n * @returns {ResumableMultiRegex}\n */\n function buildModeRegex(mode) {\n const mm = new ResumableMultiRegex();\n\n mode.contains.forEach(term => mm.addRule(term.begin, { rule: term, type: \"begin\" }));\n\n if (mode.terminatorEnd) {\n mm.addRule(mode.terminatorEnd, { type: \"end\" });\n }\n if (mode.illegal) {\n mm.addRule(mode.illegal, { type: \"illegal\" });\n }\n\n return mm;\n }\n\n /** skip vs abort vs ignore\n *\n * @skip - The mode is still entered and exited normally (and contains rules apply),\n * but all content is held and added to the parent buffer rather than being\n * output when the mode ends. Mostly used with `sublanguage` to build up\n * a single large buffer than can be parsed by sublanguage.\n *\n * - The mode begin ands ends normally.\n * - Content matched is added to the parent mode buffer.\n * - The parser cursor is moved forward normally.\n *\n * @abort - A hack placeholder until we have ignore. Aborts the mode (as if it\n * never matched) but DOES NOT continue to match subsequent `contains`\n * modes. Abort is bad/suboptimal because it can result in modes\n * farther down not getting applied because an earlier rule eats the\n * content but then aborts.\n *\n * - The mode does not begin.\n * - Content matched by `begin` is added to the mode buffer.\n * - The parser cursor is moved forward accordingly.\n *\n * @ignore - Ignores the mode (as if it never matched) and continues to match any\n * subsequent `contains` modes. Ignore isn't technically possible with\n * the current parser implementation.\n *\n * - The mode does not begin.\n * - Content matched by `begin` is ignored.\n * - The parser cursor is not moved forward.\n */\n\n /**\n * Compiles an individual mode\n *\n * This can raise an error if the mode contains certain detectable known logic\n * issues.\n * @param {Mode} mode\n * @param {CompiledMode | null} [parent]\n * @returns {CompiledMode | never}\n */\n function compileMode(mode, parent) {\n const cmode = /** @type CompiledMode */ (mode);\n if (mode.isCompiled) return cmode;\n\n [\n // do this early so compiler extensions generally don't have to worry about\n // the distinction between match/begin\n compileMatch\n ].forEach(ext => ext(mode, parent));\n\n language.compilerExtensions.forEach(ext => ext(mode, parent));\n\n // __beforeBegin is considered private API, internal use only\n mode.__beforeBegin = null;\n\n [\n beginKeywords,\n // do this later so compiler extensions that come earlier have access to the\n // raw array if they wanted to perhaps manipulate it, etc.\n compileIllegal,\n // default to 1 relevance if not specified\n compileRelevance\n ].forEach(ext => ext(mode, parent));\n\n mode.isCompiled = true;\n\n let keywordPattern = null;\n if (typeof mode.keywords === \"object\") {\n keywordPattern = mode.keywords.$pattern;\n delete mode.keywords.$pattern;\n }\n\n if (mode.keywords) {\n mode.keywords = compileKeywords(mode.keywords, language.case_insensitive);\n }\n\n // both are not allowed\n if (mode.lexemes && keywordPattern) {\n throw new Error(\"ERR: Prefer `keywords.$pattern` to `mode.lexemes`, BOTH are not allowed. (see mode reference) \");\n }\n\n // `mode.lexemes` was the old standard before we added and now recommend\n // using `keywords.$pattern` to pass the keyword pattern\n keywordPattern = keywordPattern || mode.lexemes || /\\w+/;\n cmode.keywordPatternRe = langRe(keywordPattern, true);\n\n if (parent) {\n if (!mode.begin) mode.begin = /\\B|\\b/;\n cmode.beginRe = langRe(mode.begin);\n if (mode.endSameAsBegin) mode.end = mode.begin;\n if (!mode.end && !mode.endsWithParent) mode.end = /\\B|\\b/;\n if (mode.end) cmode.endRe = langRe(mode.end);\n cmode.terminatorEnd = source(mode.end) || '';\n if (mode.endsWithParent && parent.terminatorEnd) {\n cmode.terminatorEnd += (mode.end ? '|' : '') + parent.terminatorEnd;\n }\n }\n if (mode.illegal) cmode.illegalRe = langRe(/** @type {RegExp | string} */ (mode.illegal));\n if (!mode.contains) mode.contains = [];\n\n mode.contains = [].concat(...mode.contains.map(function(c) {\n return expandOrCloneMode(c === 'self' ? mode : c);\n }));\n mode.contains.forEach(function(c) { compileMode(/** @type Mode */ (c), cmode); });\n\n if (mode.starts) {\n compileMode(mode.starts, parent);\n }\n\n cmode.matcher = buildModeRegex(cmode);\n return cmode;\n }\n\n if (!language.compilerExtensions) language.compilerExtensions = [];\n\n // self is not valid at the top-level\n if (language.contains && language.contains.includes('self')) {\n throw new Error(\"ERR: contains `self` is not supported at the top-level of a language. See documentation.\");\n }\n\n // we need a null object, which inherit will guarantee\n language.classNameAliases = inherit(language.classNameAliases || {});\n\n return compileMode(/** @type Mode */ (language));\n}\n\n/**\n * Determines if a mode has a dependency on it's parent or not\n *\n * If a mode does have a parent dependency then often we need to clone it if\n * it's used in multiple places so that each copy points to the correct parent,\n * where-as modes without a parent can often safely be re-used at the bottom of\n * a mode chain.\n *\n * @param {Mode | null} mode\n * @returns {boolean} - is there a dependency on the parent?\n * */\nfunction dependencyOnParent(mode) {\n if (!mode) return false;\n\n return mode.endsWithParent || dependencyOnParent(mode.starts);\n}\n\n/**\n * Expands a mode or clones it if necessary\n *\n * This is necessary for modes with parental dependenceis (see notes on\n * `dependencyOnParent`) and for nodes that have `variants` - which must then be\n * exploded into their own individual modes at compile time.\n *\n * @param {Mode} mode\n * @returns {Mode | Mode[]}\n * */\nfunction expandOrCloneMode(mode) {\n if (mode.variants && !mode.cachedVariants) {\n mode.cachedVariants = mode.variants.map(function(variant) {\n return inherit(mode, { variants: null }, variant);\n });\n }\n\n // EXPAND\n // if we have variants then essentially \"replace\" the mode with the variants\n // this happens in compileMode, where this function is called from\n if (mode.cachedVariants) {\n return mode.cachedVariants;\n }\n\n // CLONE\n // if we have dependencies on parents then we need a unique\n // instance of ourselves, so we can be reused with many\n // different parents without issue\n if (dependencyOnParent(mode)) {\n return inherit(mode, { starts: mode.starts ? inherit(mode.starts) : null });\n }\n\n if (Object.isFrozen(mode)) {\n return inherit(mode);\n }\n\n // no special dependency issues, just return ourselves\n return mode;\n}\n\nvar version = \"10.7.3\";\n\n// @ts-nocheck\n\nfunction hasValueOrEmptyAttribute(value) {\n return Boolean(value || value === \"\");\n}\n\nfunction BuildVuePlugin(hljs) {\n const Component = {\n props: [\"language\", \"code\", \"autodetect\"],\n data: function() {\n return {\n detectedLanguage: \"\",\n unknownLanguage: false\n };\n },\n computed: {\n className() {\n if (this.unknownLanguage) return \"\";\n\n return \"hljs \" + this.detectedLanguage;\n },\n highlighted() {\n // no idea what language to use, return raw code\n if (!this.autoDetect && !hljs.getLanguage(this.language)) {\n console.warn(`The language \"${this.language}\" you specified could not be found.`);\n this.unknownLanguage = true;\n return escapeHTML(this.code);\n }\n\n let result = {};\n if (this.autoDetect) {\n result = hljs.highlightAuto(this.code);\n this.detectedLanguage = result.language;\n } else {\n result = hljs.highlight(this.language, this.code, this.ignoreIllegals);\n this.detectedLanguage = this.language;\n }\n return result.value;\n },\n autoDetect() {\n return !this.language || hasValueOrEmptyAttribute(this.autodetect);\n },\n ignoreIllegals() {\n return true;\n }\n },\n // this avoids needing to use a whole Vue compilation pipeline just\n // to build Highlight.js\n render(createElement) {\n return createElement(\"pre\", {}, [\n createElement(\"code\", {\n class: this.className,\n domProps: { innerHTML: this.highlighted }\n })\n ]);\n }\n // template: `
      `\n };\n\n const VuePlugin = {\n install(Vue) {\n Vue.component('highlightjs', Component);\n }\n };\n\n return { Component, VuePlugin };\n}\n\n/* plugin itself */\n\n/** @type {HLJSPlugin} */\nconst mergeHTMLPlugin = {\n \"after:highlightElement\": ({ el, result, text }) => {\n const originalStream = nodeStream(el);\n if (!originalStream.length) return;\n\n const resultNode = document.createElement('div');\n resultNode.innerHTML = result.value;\n result.value = mergeStreams(originalStream, nodeStream(resultNode), text);\n }\n};\n\n/* Stream merging support functions */\n\n/**\n * @typedef Event\n * @property {'start'|'stop'} event\n * @property {number} offset\n * @property {Node} node\n */\n\n/**\n * @param {Node} node\n */\nfunction tag(node) {\n return node.nodeName.toLowerCase();\n}\n\n/**\n * @param {Node} node\n */\nfunction nodeStream(node) {\n /** @type Event[] */\n const result = [];\n (function _nodeStream(node, offset) {\n for (let child = node.firstChild; child; child = child.nextSibling) {\n if (child.nodeType === 3) {\n offset += child.nodeValue.length;\n } else if (child.nodeType === 1) {\n result.push({\n event: 'start',\n offset: offset,\n node: child\n });\n offset = _nodeStream(child, offset);\n // Prevent void elements from having an end tag that would actually\n // double them in the output. There are more void elements in HTML\n // but we list only those realistically expected in code display.\n if (!tag(child).match(/br|hr|img|input/)) {\n result.push({\n event: 'stop',\n offset: offset,\n node: child\n });\n }\n }\n }\n return offset;\n })(node, 0);\n return result;\n}\n\n/**\n * @param {any} original - the original stream\n * @param {any} highlighted - stream of the highlighted source\n * @param {string} value - the original source itself\n */\nfunction mergeStreams(original, highlighted, value) {\n let processed = 0;\n let result = '';\n const nodeStack = [];\n\n function selectStream() {\n if (!original.length || !highlighted.length) {\n return original.length ? original : highlighted;\n }\n if (original[0].offset !== highlighted[0].offset) {\n return (original[0].offset < highlighted[0].offset) ? original : highlighted;\n }\n\n /*\n To avoid starting the stream just before it should stop the order is\n ensured that original always starts first and closes last:\n\n if (event1 == 'start' && event2 == 'start')\n return original;\n if (event1 == 'start' && event2 == 'stop')\n return highlighted;\n if (event1 == 'stop' && event2 == 'start')\n return original;\n if (event1 == 'stop' && event2 == 'stop')\n return highlighted;\n\n ... which is collapsed to:\n */\n return highlighted[0].event === 'start' ? original : highlighted;\n }\n\n /**\n * @param {Node} node\n */\n function open(node) {\n /** @param {Attr} attr */\n function attributeString(attr) {\n return ' ' + attr.nodeName + '=\"' + escapeHTML(attr.value) + '\"';\n }\n // @ts-ignore\n result += '<' + tag(node) + [].map.call(node.attributes, attributeString).join('') + '>';\n }\n\n /**\n * @param {Node} node\n */\n function close(node) {\n result += '';\n }\n\n /**\n * @param {Event} event\n */\n function render(event) {\n (event.event === 'start' ? open : close)(event.node);\n }\n\n while (original.length || highlighted.length) {\n let stream = selectStream();\n result += escapeHTML(value.substring(processed, stream[0].offset));\n processed = stream[0].offset;\n if (stream === original) {\n /*\n On any opening or closing tag of the original markup we first close\n the entire highlighted node stack, then render the original tag along\n with all the following original tags at the same offset and then\n reopen all the tags on the highlighted stack.\n */\n nodeStack.reverse().forEach(close);\n do {\n render(stream.splice(0, 1)[0]);\n stream = selectStream();\n } while (stream === original && stream.length && stream[0].offset === processed);\n nodeStack.reverse().forEach(open);\n } else {\n if (stream[0].event === 'start') {\n nodeStack.push(stream[0].node);\n } else {\n nodeStack.pop();\n }\n render(stream.splice(0, 1)[0]);\n }\n }\n return result + escapeHTML(value.substr(processed));\n}\n\n/*\n\nFor the reasoning behind this please see:\nhttps://github.com/highlightjs/highlight.js/issues/2880#issuecomment-747275419\n\n*/\n\n/**\n * @type {Record}\n */\nconst seenDeprecations = {};\n\n/**\n * @param {string} message\n */\nconst error = (message) => {\n console.error(message);\n};\n\n/**\n * @param {string} message\n * @param {any} args\n */\nconst warn = (message, ...args) => {\n console.log(`WARN: ${message}`, ...args);\n};\n\n/**\n * @param {string} version\n * @param {string} message\n */\nconst deprecated = (version, message) => {\n if (seenDeprecations[`${version}/${message}`]) return;\n\n console.log(`Deprecated as of ${version}. ${message}`);\n seenDeprecations[`${version}/${message}`] = true;\n};\n\n/*\nSyntax highlighting with language autodetection.\nhttps://highlightjs.org/\n*/\n\nconst escape$1 = escapeHTML;\nconst inherit$1 = inherit;\nconst NO_MATCH = Symbol(\"nomatch\");\n\n/**\n * @param {any} hljs - object that is extended (legacy)\n * @returns {HLJSApi}\n */\nconst HLJS = function(hljs) {\n // Global internal variables used within the highlight.js library.\n /** @type {Record} */\n const languages = Object.create(null);\n /** @type {Record} */\n const aliases = Object.create(null);\n /** @type {HLJSPlugin[]} */\n const plugins = [];\n\n // safe/production mode - swallows more errors, tries to keep running\n // even if a single syntax or parse hits a fatal error\n let SAFE_MODE = true;\n const fixMarkupRe = /(^(<[^>]+>|\\t|)+|\\n)/gm;\n const LANGUAGE_NOT_FOUND = \"Could not find the language '{}', did you forget to load/include a language module?\";\n /** @type {Language} */\n const PLAINTEXT_LANGUAGE = { disableAutodetect: true, name: 'Plain text', contains: [] };\n\n // Global options used when within external APIs. This is modified when\n // calling the `hljs.configure` function.\n /** @type HLJSOptions */\n let options = {\n noHighlightRe: /^(no-?highlight)$/i,\n languageDetectRe: /\\blang(?:uage)?-([\\w-]+)\\b/i,\n classPrefix: 'hljs-',\n tabReplace: null,\n useBR: false,\n languages: null,\n // beta configuration options, subject to change, welcome to discuss\n // https://github.com/highlightjs/highlight.js/issues/1086\n __emitter: TokenTreeEmitter\n };\n\n /* Utility functions */\n\n /**\n * Tests a language name to see if highlighting should be skipped\n * @param {string} languageName\n */\n function shouldNotHighlight(languageName) {\n return options.noHighlightRe.test(languageName);\n }\n\n /**\n * @param {HighlightedHTMLElement} block - the HTML element to determine language for\n */\n function blockLanguage(block) {\n let classes = block.className + ' ';\n\n classes += block.parentNode ? block.parentNode.className : '';\n\n // language-* takes precedence over non-prefixed class names.\n const match = options.languageDetectRe.exec(classes);\n if (match) {\n const language = getLanguage(match[1]);\n if (!language) {\n warn(LANGUAGE_NOT_FOUND.replace(\"{}\", match[1]));\n warn(\"Falling back to no-highlight mode for this block.\", block);\n }\n return language ? match[1] : 'no-highlight';\n }\n\n return classes\n .split(/\\s+/)\n .find((_class) => shouldNotHighlight(_class) || getLanguage(_class));\n }\n\n /**\n * Core highlighting function.\n *\n * OLD API\n * highlight(lang, code, ignoreIllegals, continuation)\n *\n * NEW API\n * highlight(code, {lang, ignoreIllegals})\n *\n * @param {string} codeOrlanguageName - the language to use for highlighting\n * @param {string | HighlightOptions} optionsOrCode - the code to highlight\n * @param {boolean} [ignoreIllegals] - whether to ignore illegal matches, default is to bail\n * @param {CompiledMode} [continuation] - current continuation mode, if any\n *\n * @returns {HighlightResult} Result - an object that represents the result\n * @property {string} language - the language name\n * @property {number} relevance - the relevance score\n * @property {string} value - the highlighted HTML code\n * @property {string} code - the original raw code\n * @property {CompiledMode} top - top of the current mode stack\n * @property {boolean} illegal - indicates whether any illegal matches were found\n */\n function highlight(codeOrlanguageName, optionsOrCode, ignoreIllegals, continuation) {\n let code = \"\";\n let languageName = \"\";\n if (typeof optionsOrCode === \"object\") {\n code = codeOrlanguageName;\n ignoreIllegals = optionsOrCode.ignoreIllegals;\n languageName = optionsOrCode.language;\n // continuation not supported at all via the new API\n // eslint-disable-next-line no-undefined\n continuation = undefined;\n } else {\n // old API\n deprecated(\"10.7.0\", \"highlight(lang, code, ...args) has been deprecated.\");\n deprecated(\"10.7.0\", \"Please use highlight(code, options) instead.\\nhttps://github.com/highlightjs/highlight.js/issues/2277\");\n languageName = codeOrlanguageName;\n code = optionsOrCode;\n }\n\n /** @type {BeforeHighlightContext} */\n const context = {\n code,\n language: languageName\n };\n // the plugin can change the desired language or the code to be highlighted\n // just be changing the object it was passed\n fire(\"before:highlight\", context);\n\n // a before plugin can usurp the result completely by providing it's own\n // in which case we don't even need to call highlight\n const result = context.result\n ? context.result\n : _highlight(context.language, context.code, ignoreIllegals, continuation);\n\n result.code = context.code;\n // the plugin can change anything in result to suite it\n fire(\"after:highlight\", result);\n\n return result;\n }\n\n /**\n * private highlight that's used internally and does not fire callbacks\n *\n * @param {string} languageName - the language to use for highlighting\n * @param {string} codeToHighlight - the code to highlight\n * @param {boolean?} [ignoreIllegals] - whether to ignore illegal matches, default is to bail\n * @param {CompiledMode?} [continuation] - current continuation mode, if any\n * @returns {HighlightResult} - result of the highlight operation\n */\n function _highlight(languageName, codeToHighlight, ignoreIllegals, continuation) {\n /**\n * Return keyword data if a match is a keyword\n * @param {CompiledMode} mode - current mode\n * @param {RegExpMatchArray} match - regexp match data\n * @returns {KeywordData | false}\n */\n function keywordData(mode, match) {\n const matchText = language.case_insensitive ? match[0].toLowerCase() : match[0];\n return Object.prototype.hasOwnProperty.call(mode.keywords, matchText) && mode.keywords[matchText];\n }\n\n function processKeywords() {\n if (!top.keywords) {\n emitter.addText(modeBuffer);\n return;\n }\n\n let lastIndex = 0;\n top.keywordPatternRe.lastIndex = 0;\n let match = top.keywordPatternRe.exec(modeBuffer);\n let buf = \"\";\n\n while (match) {\n buf += modeBuffer.substring(lastIndex, match.index);\n const data = keywordData(top, match);\n if (data) {\n const [kind, keywordRelevance] = data;\n emitter.addText(buf);\n buf = \"\";\n\n relevance += keywordRelevance;\n if (kind.startsWith(\"_\")) {\n // _ implied for relevance only, do not highlight\n // by applying a class name\n buf += match[0];\n } else {\n const cssClass = language.classNameAliases[kind] || kind;\n emitter.addKeyword(match[0], cssClass);\n }\n } else {\n buf += match[0];\n }\n lastIndex = top.keywordPatternRe.lastIndex;\n match = top.keywordPatternRe.exec(modeBuffer);\n }\n buf += modeBuffer.substr(lastIndex);\n emitter.addText(buf);\n }\n\n function processSubLanguage() {\n if (modeBuffer === \"\") return;\n /** @type HighlightResult */\n let result = null;\n\n if (typeof top.subLanguage === 'string') {\n if (!languages[top.subLanguage]) {\n emitter.addText(modeBuffer);\n return;\n }\n result = _highlight(top.subLanguage, modeBuffer, true, continuations[top.subLanguage]);\n continuations[top.subLanguage] = /** @type {CompiledMode} */ (result.top);\n } else {\n result = highlightAuto(modeBuffer, top.subLanguage.length ? top.subLanguage : null);\n }\n\n // Counting embedded language score towards the host language may be disabled\n // with zeroing the containing mode relevance. Use case in point is Markdown that\n // allows XML everywhere and makes every XML snippet to have a much larger Markdown\n // score.\n if (top.relevance > 0) {\n relevance += result.relevance;\n }\n emitter.addSublanguage(result.emitter, result.language);\n }\n\n function processBuffer() {\n if (top.subLanguage != null) {\n processSubLanguage();\n } else {\n processKeywords();\n }\n modeBuffer = '';\n }\n\n /**\n * @param {Mode} mode - new mode to start\n */\n function startNewMode(mode) {\n if (mode.className) {\n emitter.openNode(language.classNameAliases[mode.className] || mode.className);\n }\n top = Object.create(mode, { parent: { value: top } });\n return top;\n }\n\n /**\n * @param {CompiledMode } mode - the mode to potentially end\n * @param {RegExpMatchArray} match - the latest match\n * @param {string} matchPlusRemainder - match plus remainder of content\n * @returns {CompiledMode | void} - the next mode, or if void continue on in current mode\n */\n function endOfMode(mode, match, matchPlusRemainder) {\n let matched = startsWith(mode.endRe, matchPlusRemainder);\n\n if (matched) {\n if (mode[\"on:end\"]) {\n const resp = new Response(mode);\n mode[\"on:end\"](match, resp);\n if (resp.isMatchIgnored) matched = false;\n }\n\n if (matched) {\n while (mode.endsParent && mode.parent) {\n mode = mode.parent;\n }\n return mode;\n }\n }\n // even if on:end fires an `ignore` it's still possible\n // that we might trigger the end node because of a parent mode\n if (mode.endsWithParent) {\n return endOfMode(mode.parent, match, matchPlusRemainder);\n }\n }\n\n /**\n * Handle matching but then ignoring a sequence of text\n *\n * @param {string} lexeme - string containing full match text\n */\n function doIgnore(lexeme) {\n if (top.matcher.regexIndex === 0) {\n // no more regexs to potentially match here, so we move the cursor forward one\n // space\n modeBuffer += lexeme[0];\n return 1;\n } else {\n // no need to move the cursor, we still have additional regexes to try and\n // match at this very spot\n resumeScanAtSamePosition = true;\n return 0;\n }\n }\n\n /**\n * Handle the start of a new potential mode match\n *\n * @param {EnhancedMatch} match - the current match\n * @returns {number} how far to advance the parse cursor\n */\n function doBeginMatch(match) {\n const lexeme = match[0];\n const newMode = match.rule;\n\n const resp = new Response(newMode);\n // first internal before callbacks, then the public ones\n const beforeCallbacks = [newMode.__beforeBegin, newMode[\"on:begin\"]];\n for (const cb of beforeCallbacks) {\n if (!cb) continue;\n cb(match, resp);\n if (resp.isMatchIgnored) return doIgnore(lexeme);\n }\n\n if (newMode && newMode.endSameAsBegin) {\n newMode.endRe = escape(lexeme);\n }\n\n if (newMode.skip) {\n modeBuffer += lexeme;\n } else {\n if (newMode.excludeBegin) {\n modeBuffer += lexeme;\n }\n processBuffer();\n if (!newMode.returnBegin && !newMode.excludeBegin) {\n modeBuffer = lexeme;\n }\n }\n startNewMode(newMode);\n // if (mode[\"after:begin\"]) {\n // let resp = new Response(mode);\n // mode[\"after:begin\"](match, resp);\n // }\n return newMode.returnBegin ? 0 : lexeme.length;\n }\n\n /**\n * Handle the potential end of mode\n *\n * @param {RegExpMatchArray} match - the current match\n */\n function doEndMatch(match) {\n const lexeme = match[0];\n const matchPlusRemainder = codeToHighlight.substr(match.index);\n\n const endMode = endOfMode(top, match, matchPlusRemainder);\n if (!endMode) { return NO_MATCH; }\n\n const origin = top;\n if (origin.skip) {\n modeBuffer += lexeme;\n } else {\n if (!(origin.returnEnd || origin.excludeEnd)) {\n modeBuffer += lexeme;\n }\n processBuffer();\n if (origin.excludeEnd) {\n modeBuffer = lexeme;\n }\n }\n do {\n if (top.className) {\n emitter.closeNode();\n }\n if (!top.skip && !top.subLanguage) {\n relevance += top.relevance;\n }\n top = top.parent;\n } while (top !== endMode.parent);\n if (endMode.starts) {\n if (endMode.endSameAsBegin) {\n endMode.starts.endRe = endMode.endRe;\n }\n startNewMode(endMode.starts);\n }\n return origin.returnEnd ? 0 : lexeme.length;\n }\n\n function processContinuations() {\n const list = [];\n for (let current = top; current !== language; current = current.parent) {\n if (current.className) {\n list.unshift(current.className);\n }\n }\n list.forEach(item => emitter.openNode(item));\n }\n\n /** @type {{type?: MatchType, index?: number, rule?: Mode}}} */\n let lastMatch = {};\n\n /**\n * Process an individual match\n *\n * @param {string} textBeforeMatch - text preceeding the match (since the last match)\n * @param {EnhancedMatch} [match] - the match itself\n */\n function processLexeme(textBeforeMatch, match) {\n const lexeme = match && match[0];\n\n // add non-matched text to the current mode buffer\n modeBuffer += textBeforeMatch;\n\n if (lexeme == null) {\n processBuffer();\n return 0;\n }\n\n // we've found a 0 width match and we're stuck, so we need to advance\n // this happens when we have badly behaved rules that have optional matchers to the degree that\n // sometimes they can end up matching nothing at all\n // Ref: https://github.com/highlightjs/highlight.js/issues/2140\n if (lastMatch.type === \"begin\" && match.type === \"end\" && lastMatch.index === match.index && lexeme === \"\") {\n // spit the \"skipped\" character that our regex choked on back into the output sequence\n modeBuffer += codeToHighlight.slice(match.index, match.index + 1);\n if (!SAFE_MODE) {\n /** @type {AnnotatedError} */\n const err = new Error('0 width match regex');\n err.languageName = languageName;\n err.badRule = lastMatch.rule;\n throw err;\n }\n return 1;\n }\n lastMatch = match;\n\n if (match.type === \"begin\") {\n return doBeginMatch(match);\n } else if (match.type === \"illegal\" && !ignoreIllegals) {\n // illegal match, we do not continue processing\n /** @type {AnnotatedError} */\n const err = new Error('Illegal lexeme \"' + lexeme + '\" for mode \"' + (top.className || '') + '\"');\n err.mode = top;\n throw err;\n } else if (match.type === \"end\") {\n const processed = doEndMatch(match);\n if (processed !== NO_MATCH) {\n return processed;\n }\n }\n\n // edge case for when illegal matches $ (end of line) which is technically\n // a 0 width match but not a begin/end match so it's not caught by the\n // first handler (when ignoreIllegals is true)\n if (match.type === \"illegal\" && lexeme === \"\") {\n // advance so we aren't stuck in an infinite loop\n return 1;\n }\n\n // infinite loops are BAD, this is a last ditch catch all. if we have a\n // decent number of iterations yet our index (cursor position in our\n // parsing) still 3x behind our index then something is very wrong\n // so we bail\n if (iterations > 100000 && iterations > match.index * 3) {\n const err = new Error('potential infinite loop, way more iterations than matches');\n throw err;\n }\n\n /*\n Why might be find ourselves here? Only one occasion now. An end match that was\n triggered but could not be completed. When might this happen? When an `endSameasBegin`\n rule sets the end rule to a specific match. Since the overall mode termination rule that's\n being used to scan the text isn't recompiled that means that any match that LOOKS like\n the end (but is not, because it is not an exact match to the beginning) will\n end up here. A definite end match, but when `doEndMatch` tries to \"reapply\"\n the end rule and fails to match, we wind up here, and just silently ignore the end.\n\n This causes no real harm other than stopping a few times too many.\n */\n\n modeBuffer += lexeme;\n return lexeme.length;\n }\n\n const language = getLanguage(languageName);\n if (!language) {\n error(LANGUAGE_NOT_FOUND.replace(\"{}\", languageName));\n throw new Error('Unknown language: \"' + languageName + '\"');\n }\n\n const md = compileLanguage(language, { plugins });\n let result = '';\n /** @type {CompiledMode} */\n let top = continuation || md;\n /** @type Record */\n const continuations = {}; // keep continuations for sub-languages\n const emitter = new options.__emitter(options);\n processContinuations();\n let modeBuffer = '';\n let relevance = 0;\n let index = 0;\n let iterations = 0;\n let resumeScanAtSamePosition = false;\n\n try {\n top.matcher.considerAll();\n\n for (;;) {\n iterations++;\n if (resumeScanAtSamePosition) {\n // only regexes not matched previously will now be\n // considered for a potential match\n resumeScanAtSamePosition = false;\n } else {\n top.matcher.considerAll();\n }\n top.matcher.lastIndex = index;\n\n const match = top.matcher.exec(codeToHighlight);\n // console.log(\"match\", match[0], match.rule && match.rule.begin)\n\n if (!match) break;\n\n const beforeMatch = codeToHighlight.substring(index, match.index);\n const processedCount = processLexeme(beforeMatch, match);\n index = match.index + processedCount;\n }\n processLexeme(codeToHighlight.substr(index));\n emitter.closeAllNodes();\n emitter.finalize();\n result = emitter.toHTML();\n\n return {\n // avoid possible breakage with v10 clients expecting\n // this to always be an integer\n relevance: Math.floor(relevance),\n value: result,\n language: languageName,\n illegal: false,\n emitter: emitter,\n top: top\n };\n } catch (err) {\n if (err.message && err.message.includes('Illegal')) {\n return {\n illegal: true,\n illegalBy: {\n msg: err.message,\n context: codeToHighlight.slice(index - 100, index + 100),\n mode: err.mode\n },\n sofar: result,\n relevance: 0,\n value: escape$1(codeToHighlight),\n emitter: emitter\n };\n } else if (SAFE_MODE) {\n return {\n illegal: false,\n relevance: 0,\n value: escape$1(codeToHighlight),\n emitter: emitter,\n language: languageName,\n top: top,\n errorRaised: err\n };\n } else {\n throw err;\n }\n }\n }\n\n /**\n * returns a valid highlight result, without actually doing any actual work,\n * auto highlight starts with this and it's possible for small snippets that\n * auto-detection may not find a better match\n * @param {string} code\n * @returns {HighlightResult}\n */\n function justTextHighlightResult(code) {\n const result = {\n relevance: 0,\n emitter: new options.__emitter(options),\n value: escape$1(code),\n illegal: false,\n top: PLAINTEXT_LANGUAGE\n };\n result.emitter.addText(code);\n return result;\n }\n\n /**\n Highlighting with language detection. Accepts a string with the code to\n highlight. Returns an object with the following properties:\n\n - language (detected language)\n - relevance (int)\n - value (an HTML string with highlighting markup)\n - second_best (object with the same structure for second-best heuristically\n detected language, may be absent)\n\n @param {string} code\n @param {Array} [languageSubset]\n @returns {AutoHighlightResult}\n */\n function highlightAuto(code, languageSubset) {\n languageSubset = languageSubset || options.languages || Object.keys(languages);\n const plaintext = justTextHighlightResult(code);\n\n const results = languageSubset.filter(getLanguage).filter(autoDetection).map(name =>\n _highlight(name, code, false)\n );\n results.unshift(plaintext); // plaintext is always an option\n\n const sorted = results.sort((a, b) => {\n // sort base on relevance\n if (a.relevance !== b.relevance) return b.relevance - a.relevance;\n\n // always award the tie to the base language\n // ie if C++ and Arduino are tied, it's more likely to be C++\n if (a.language && b.language) {\n if (getLanguage(a.language).supersetOf === b.language) {\n return 1;\n } else if (getLanguage(b.language).supersetOf === a.language) {\n return -1;\n }\n }\n\n // otherwise say they are equal, which has the effect of sorting on\n // relevance while preserving the original ordering - which is how ties\n // have historically been settled, ie the language that comes first always\n // wins in the case of a tie\n return 0;\n });\n\n const [best, secondBest] = sorted;\n\n /** @type {AutoHighlightResult} */\n const result = best;\n result.second_best = secondBest;\n\n return result;\n }\n\n /**\n Post-processing of the highlighted markup:\n\n - replace TABs with something more useful\n - replace real line-breaks with '
      ' for non-pre containers\n\n @param {string} html\n @returns {string}\n */\n function fixMarkup(html) {\n if (!(options.tabReplace || options.useBR)) {\n return html;\n }\n\n return html.replace(fixMarkupRe, match => {\n if (match === '\\n') {\n return options.useBR ? '
      ' : match;\n } else if (options.tabReplace) {\n return match.replace(/\\t/g, options.tabReplace);\n }\n return match;\n });\n }\n\n /**\n * Builds new class name for block given the language name\n *\n * @param {HTMLElement} element\n * @param {string} [currentLang]\n * @param {string} [resultLang]\n */\n function updateClassName(element, currentLang, resultLang) {\n const language = currentLang ? aliases[currentLang] : resultLang;\n\n element.classList.add(\"hljs\");\n if (language) element.classList.add(language);\n }\n\n /** @type {HLJSPlugin} */\n const brPlugin = {\n \"before:highlightElement\": ({ el }) => {\n if (options.useBR) {\n el.innerHTML = el.innerHTML.replace(/\\n/g, '').replace(//g, '\\n');\n }\n },\n \"after:highlightElement\": ({ result }) => {\n if (options.useBR) {\n result.value = result.value.replace(/\\n/g, \"
      \");\n }\n }\n };\n\n const TAB_REPLACE_RE = /^(<[^>]+>|\\t)+/gm;\n /** @type {HLJSPlugin} */\n const tabReplacePlugin = {\n \"after:highlightElement\": ({ result }) => {\n if (options.tabReplace) {\n result.value = result.value.replace(TAB_REPLACE_RE, (m) =>\n m.replace(/\\t/g, options.tabReplace)\n );\n }\n }\n };\n\n /**\n * Applies highlighting to a DOM node containing code. Accepts a DOM node and\n * two optional parameters for fixMarkup.\n *\n * @param {HighlightedHTMLElement} element - the HTML element to highlight\n */\n function highlightElement(element) {\n /** @type HTMLElement */\n let node = null;\n const language = blockLanguage(element);\n\n if (shouldNotHighlight(language)) return;\n\n // support for v10 API\n fire(\"before:highlightElement\",\n { el: element, language: language });\n\n node = element;\n const text = node.textContent;\n const result = language ? highlight(text, { language, ignoreIllegals: true }) : highlightAuto(text);\n\n // support for v10 API\n fire(\"after:highlightElement\", { el: element, result, text });\n\n element.innerHTML = result.value;\n updateClassName(element, language, result.language);\n element.result = {\n language: result.language,\n // TODO: remove with version 11.0\n re: result.relevance,\n relavance: result.relevance\n };\n if (result.second_best) {\n element.second_best = {\n language: result.second_best.language,\n // TODO: remove with version 11.0\n re: result.second_best.relevance,\n relavance: result.second_best.relevance\n };\n }\n }\n\n /**\n * Updates highlight.js global options with the passed options\n *\n * @param {Partial} userOptions\n */\n function configure(userOptions) {\n if (userOptions.useBR) {\n deprecated(\"10.3.0\", \"'useBR' will be removed entirely in v11.0\");\n deprecated(\"10.3.0\", \"Please see https://github.com/highlightjs/highlight.js/issues/2559\");\n }\n options = inherit$1(options, userOptions);\n }\n\n /**\n * Highlights to all
       blocks on a page\n   *\n   * @type {Function & {called?: boolean}}\n   */\n  // TODO: remove v12, deprecated\n  const initHighlighting = () => {\n    if (initHighlighting.called) return;\n    initHighlighting.called = true;\n\n    deprecated(\"10.6.0\", \"initHighlighting() is deprecated.  Use highlightAll() instead.\");\n\n    const blocks = document.querySelectorAll('pre code');\n    blocks.forEach(highlightElement);\n  };\n\n  // Higlights all when DOMContentLoaded fires\n  // TODO: remove v12, deprecated\n  function initHighlightingOnLoad() {\n    deprecated(\"10.6.0\", \"initHighlightingOnLoad() is deprecated.  Use highlightAll() instead.\");\n    wantsHighlight = true;\n  }\n\n  let wantsHighlight = false;\n\n  /**\n   * auto-highlights all pre>code elements on the page\n   */\n  function highlightAll() {\n    // if we are called too early in the loading process\n    if (document.readyState === \"loading\") {\n      wantsHighlight = true;\n      return;\n    }\n\n    const blocks = document.querySelectorAll('pre code');\n    blocks.forEach(highlightElement);\n  }\n\n  function boot() {\n    // if a highlight was requested before DOM was loaded, do now\n    if (wantsHighlight) highlightAll();\n  }\n\n  // make sure we are in the browser environment\n  if (typeof window !== 'undefined' && window.addEventListener) {\n    window.addEventListener('DOMContentLoaded', boot, false);\n  }\n\n  /**\n   * Register a language grammar module\n   *\n   * @param {string} languageName\n   * @param {LanguageFn} languageDefinition\n   */\n  function registerLanguage(languageName, languageDefinition) {\n    let lang = null;\n    try {\n      lang = languageDefinition(hljs);\n    } catch (error$1) {\n      error(\"Language definition for '{}' could not be registered.\".replace(\"{}\", languageName));\n      // hard or soft error\n      if (!SAFE_MODE) { throw error$1; } else { error(error$1); }\n      // languages that have serious errors are replaced with essentially a\n      // \"plaintext\" stand-in so that the code blocks will still get normal\n      // css classes applied to them - and one bad language won't break the\n      // entire highlighter\n      lang = PLAINTEXT_LANGUAGE;\n    }\n    // give it a temporary name if it doesn't have one in the meta-data\n    if (!lang.name) lang.name = languageName;\n    languages[languageName] = lang;\n    lang.rawDefinition = languageDefinition.bind(null, hljs);\n\n    if (lang.aliases) {\n      registerAliases(lang.aliases, { languageName });\n    }\n  }\n\n  /**\n   * Remove a language grammar module\n   *\n   * @param {string} languageName\n   */\n  function unregisterLanguage(languageName) {\n    delete languages[languageName];\n    for (const alias of Object.keys(aliases)) {\n      if (aliases[alias] === languageName) {\n        delete aliases[alias];\n      }\n    }\n  }\n\n  /**\n   * @returns {string[]} List of language internal names\n   */\n  function listLanguages() {\n    return Object.keys(languages);\n  }\n\n  /**\n    intended usage: When one language truly requires another\n\n    Unlike `getLanguage`, this will throw when the requested language\n    is not available.\n\n    @param {string} name - name of the language to fetch/require\n    @returns {Language | never}\n  */\n  function requireLanguage(name) {\n    deprecated(\"10.4.0\", \"requireLanguage will be removed entirely in v11.\");\n    deprecated(\"10.4.0\", \"Please see https://github.com/highlightjs/highlight.js/pull/2844\");\n\n    const lang = getLanguage(name);\n    if (lang) { return lang; }\n\n    const err = new Error('The \\'{}\\' language is required, but not loaded.'.replace('{}', name));\n    throw err;\n  }\n\n  /**\n   * @param {string} name - name of the language to retrieve\n   * @returns {Language | undefined}\n   */\n  function getLanguage(name) {\n    name = (name || '').toLowerCase();\n    return languages[name] || languages[aliases[name]];\n  }\n\n  /**\n   *\n   * @param {string|string[]} aliasList - single alias or list of aliases\n   * @param {{languageName: string}} opts\n   */\n  function registerAliases(aliasList, { languageName }) {\n    if (typeof aliasList === 'string') {\n      aliasList = [aliasList];\n    }\n    aliasList.forEach(alias => { aliases[alias.toLowerCase()] = languageName; });\n  }\n\n  /**\n   * Determines if a given language has auto-detection enabled\n   * @param {string} name - name of the language\n   */\n  function autoDetection(name) {\n    const lang = getLanguage(name);\n    return lang && !lang.disableAutodetect;\n  }\n\n  /**\n   * Upgrades the old highlightBlock plugins to the new\n   * highlightElement API\n   * @param {HLJSPlugin} plugin\n   */\n  function upgradePluginAPI(plugin) {\n    // TODO: remove with v12\n    if (plugin[\"before:highlightBlock\"] && !plugin[\"before:highlightElement\"]) {\n      plugin[\"before:highlightElement\"] = (data) => {\n        plugin[\"before:highlightBlock\"](\n          Object.assign({ block: data.el }, data)\n        );\n      };\n    }\n    if (plugin[\"after:highlightBlock\"] && !plugin[\"after:highlightElement\"]) {\n      plugin[\"after:highlightElement\"] = (data) => {\n        plugin[\"after:highlightBlock\"](\n          Object.assign({ block: data.el }, data)\n        );\n      };\n    }\n  }\n\n  /**\n   * @param {HLJSPlugin} plugin\n   */\n  function addPlugin(plugin) {\n    upgradePluginAPI(plugin);\n    plugins.push(plugin);\n  }\n\n  /**\n   *\n   * @param {PluginEvent} event\n   * @param {any} args\n   */\n  function fire(event, args) {\n    const cb = event;\n    plugins.forEach(function(plugin) {\n      if (plugin[cb]) {\n        plugin[cb](args);\n      }\n    });\n  }\n\n  /**\n  Note: fixMarkup is deprecated and will be removed entirely in v11\n\n  @param {string} arg\n  @returns {string}\n  */\n  function deprecateFixMarkup(arg) {\n    deprecated(\"10.2.0\", \"fixMarkup will be removed entirely in v11.0\");\n    deprecated(\"10.2.0\", \"Please see https://github.com/highlightjs/highlight.js/issues/2534\");\n\n    return fixMarkup(arg);\n  }\n\n  /**\n   *\n   * @param {HighlightedHTMLElement} el\n   */\n  function deprecateHighlightBlock(el) {\n    deprecated(\"10.7.0\", \"highlightBlock will be removed entirely in v12.0\");\n    deprecated(\"10.7.0\", \"Please use highlightElement now.\");\n\n    return highlightElement(el);\n  }\n\n  /* Interface definition */\n  Object.assign(hljs, {\n    highlight,\n    highlightAuto,\n    highlightAll,\n    fixMarkup: deprecateFixMarkup,\n    highlightElement,\n    // TODO: Remove with v12 API\n    highlightBlock: deprecateHighlightBlock,\n    configure,\n    initHighlighting,\n    initHighlightingOnLoad,\n    registerLanguage,\n    unregisterLanguage,\n    listLanguages,\n    getLanguage,\n    registerAliases,\n    requireLanguage,\n    autoDetection,\n    inherit: inherit$1,\n    addPlugin,\n    // plugins for frameworks\n    vuePlugin: BuildVuePlugin(hljs).VuePlugin\n  });\n\n  hljs.debugMode = function() { SAFE_MODE = false; };\n  hljs.safeMode = function() { SAFE_MODE = true; };\n  hljs.versionString = version;\n\n  for (const key in MODES) {\n    // @ts-ignore\n    if (typeof MODES[key] === \"object\") {\n      // @ts-ignore\n      deepFreezeEs6(MODES[key]);\n    }\n  }\n\n  // merge all the modes/regexs into our main object\n  Object.assign(hljs, MODES);\n\n  // built-in plugins, likely to be moved out of core in the future\n  hljs.addPlugin(brPlugin); // slated to be removed in v11\n  hljs.addPlugin(mergeHTMLPlugin);\n  hljs.addPlugin(tabReplacePlugin);\n  return hljs;\n};\n\n// export an \"instance\" of the highlighter\nvar highlight = HLJS({});\n\nmodule.exports = highlight;\n","/*\n * Copyright 2021 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the 'License');\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an 'AS IS' BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n(function () {\n  'use strict';\n\n  const highlightJs = require('highlight.js/lib/core');\n\n  highlightJs.registerLanguage('asciidoc', require('highlight.js/lib/languages/asciidoc'));\n  highlightJs.registerLanguage('bash', require('highlight.js/lib/languages/bash'));\n  highlightJs.registerLanguage('css', require('highlight.js/lib/languages/css'));\n  highlightJs.registerLanguage('diff', require('highlight.js/lib/languages/diff'));\n  highlightJs.registerLanguage('dockerfile', require('highlight.js/lib/languages/dockerfile'));\n  highlightJs.registerLanguage('dos', require('highlight.js/lib/languages/dos'));\n  highlightJs.registerLanguage('gradle', require('highlight.js/lib/languages/gradle'));\n  highlightJs.registerLanguage('groovy', require('highlight.js/lib/languages/groovy'));\n  highlightJs.registerLanguage('http', require('highlight.js/lib/languages/http'));\n  highlightJs.registerLanguage('java', require('highlight.js/lib/languages/java'));\n  highlightJs.registerLanguage('javascript',require('highlight.js/lib/languages/javascript'));\n  highlightJs.registerLanguage('json', require('highlight.js/lib/languages/json'));\n  highlightJs.registerLanguage('kotlin', require('highlight.js/lib/languages/kotlin'));\n  highlightJs.registerLanguage('markdown', require('highlight.js/lib/languages/markdown'));\n  highlightJs.registerLanguage('nix', require('highlight.js/lib/languages/nix'));\n  highlightJs.registerLanguage('powershell', require('highlight.js/lib/languages/powershell'));\n  highlightJs.registerLanguage('properties', require('highlight.js/lib/languages/properties'));\n  highlightJs.registerLanguage('ruby', require('highlight.js/lib/languages/ruby'));\n  highlightJs.registerLanguage('scala', require('highlight.js/lib/languages/scala'));\n  highlightJs.registerLanguage('shell', require('highlight.js/lib/languages/shell'));\n  highlightJs.registerLanguage('sql', require('highlight.js/lib/languages/sql'));\n  highlightJs.registerLanguage('xml', require('highlight.js/lib/languages/xml'));\n  highlightJs.registerLanguage('yaml', require('highlight.js/lib/languages/yaml'));\n\n  highlightJs.configure({ignoreUnescapedHTML: true});\n\n  for(const codeElement of document.querySelectorAll('pre.highlight > code')) {\n    highlightJs.highlightBlock(codeElement);\n  }\n\n})();\n","/**\n * @param {string} value\n * @returns {RegExp}\n * */\n\n/**\n * @param {RegExp | string } re\n * @returns {string}\n */\nfunction source(re) {\n  if (!re) return null;\n  if (typeof re === \"string\") return re;\n\n  return re.source;\n}\n\n/**\n * @param {...(RegExp | string) } args\n * @returns {string}\n */\nfunction concat(...args) {\n  const joined = args.map((x) => source(x)).join(\"\");\n  return joined;\n}\n\n/*\nLanguage: AsciiDoc\nRequires: xml.js\nAuthor: Dan Allen \nWebsite: http://asciidoc.org\nDescription: A semantic, text-based document format that can be exported to HTML, DocBook and other backends.\nCategory: markup\n*/\n\n/** @type LanguageFn */\nfunction asciidoc(hljs) {\n  const HORIZONTAL_RULE = {\n    begin: '^\\'{3,}[ \\\\t]*$',\n    relevance: 10\n  };\n  const ESCAPED_FORMATTING = [\n    // escaped constrained formatting marks (i.e., \\* \\_ or \\`)\n    {\n      begin: /\\\\[*_`]/\n    },\n    // escaped unconstrained formatting marks (i.e., \\\\** \\\\__ or \\\\``)\n    // must ignore until the next formatting marks\n    // this rule might not be 100% compliant with Asciidoctor 2.0 but we are entering undefined behavior territory...\n    {\n      begin: /\\\\\\\\\\*{2}[^\\n]*?\\*{2}/\n    },\n    {\n      begin: /\\\\\\\\_{2}[^\\n]*_{2}/\n    },\n    {\n      begin: /\\\\\\\\`{2}[^\\n]*`{2}/\n    },\n    // guard: constrained formatting mark may not be preceded by \":\", \";\" or\n    // \"}\". match these so the constrained rule doesn't see them\n    {\n      begin: /[:;}][*_`](?![*_`])/\n    }\n  ];\n  const STRONG = [\n    // inline unconstrained strong (single line)\n    {\n      className: 'strong',\n      begin: /\\*{2}([^\\n]+?)\\*{2}/\n    },\n    // inline unconstrained strong (multi-line)\n    {\n      className: 'strong',\n      begin: concat(\n        /\\*\\*/,\n        /((\\*(?!\\*)|\\\\[^\\n]|[^*\\n\\\\])+\\n)+/,\n        /(\\*(?!\\*)|\\\\[^\\n]|[^*\\n\\\\])*/,\n        /\\*\\*/\n      ),\n      relevance: 0\n    },\n    // inline constrained strong (single line)\n    {\n      className: 'strong',\n      // must not precede or follow a word character\n      begin: /\\B\\*(\\S|\\S[^\\n]*?\\S)\\*(?!\\w)/\n    },\n    // inline constrained strong (multi-line)\n    {\n      className: 'strong',\n      // must not precede or follow a word character\n      begin: /\\*[^\\s]([^\\n]+\\n)+([^\\n]+)\\*/\n    }\n  ];\n  const EMPHASIS = [\n    // inline unconstrained emphasis (single line)\n    {\n      className: 'emphasis',\n      begin: /_{2}([^\\n]+?)_{2}/\n    },\n    // inline unconstrained emphasis (multi-line)\n    {\n      className: 'emphasis',\n      begin: concat(\n        /__/,\n        /((_(?!_)|\\\\[^\\n]|[^_\\n\\\\])+\\n)+/,\n        /(_(?!_)|\\\\[^\\n]|[^_\\n\\\\])*/,\n        /__/\n      ),\n      relevance: 0\n    },\n    // inline constrained emphasis (single line)\n    {\n      className: 'emphasis',\n      // must not precede or follow a word character\n      begin: /\\b_(\\S|\\S[^\\n]*?\\S)_(?!\\w)/\n    },\n    // inline constrained emphasis (multi-line)\n    {\n      className: 'emphasis',\n      // must not precede or follow a word character\n      begin: /_[^\\s]([^\\n]+\\n)+([^\\n]+)_/\n    },\n    // inline constrained emphasis using single quote (legacy)\n    {\n      className: 'emphasis',\n      // must not follow a word character or be followed by a single quote or space\n      begin: '\\\\B\\'(?![\\'\\\\s])',\n      end: '(\\\\n{2}|\\')',\n      // allow escaped single quote followed by word char\n      contains: [{\n        begin: '\\\\\\\\\\'\\\\w',\n        relevance: 0\n      }],\n      relevance: 0\n    }\n  ];\n  const ADMONITION = {\n    className: 'symbol',\n    begin: '^(NOTE|TIP|IMPORTANT|WARNING|CAUTION):\\\\s+',\n    relevance: 10\n  };\n  const BULLET_LIST = {\n    className: 'bullet',\n    begin: '^(\\\\*+|-+|\\\\.+|[^\\\\n]+?::)\\\\s+'\n  };\n\n  return {\n    name: 'AsciiDoc',\n    aliases: ['adoc'],\n    contains: [\n      // block comment\n      hljs.COMMENT(\n        '^/{4,}\\\\n',\n        '\\\\n/{4,}$',\n        // can also be done as...\n        // '^/{4,}$',\n        // '^/{4,}$',\n        {\n          relevance: 10\n        }\n      ),\n      // line comment\n      hljs.COMMENT(\n        '^//',\n        '$',\n        {\n          relevance: 0\n        }\n      ),\n      // title\n      {\n        className: 'title',\n        begin: '^\\\\.\\\\w.*$'\n      },\n      // example, admonition & sidebar blocks\n      {\n        begin: '^[=\\\\*]{4,}\\\\n',\n        end: '\\\\n^[=\\\\*]{4,}$',\n        relevance: 10\n      },\n      // headings\n      {\n        className: 'section',\n        relevance: 10,\n        variants: [\n          {\n            begin: '^(={1,6})[ \\t].+?([ \\t]\\\\1)?$'\n          },\n          {\n            begin: '^[^\\\\[\\\\]\\\\n]+?\\\\n[=\\\\-~\\\\^\\\\+]{2,}$'\n          }\n        ]\n      },\n      // document attributes\n      {\n        className: 'meta',\n        begin: '^:.+?:',\n        end: '\\\\s',\n        excludeEnd: true,\n        relevance: 10\n      },\n      // block attributes\n      {\n        className: 'meta',\n        begin: '^\\\\[.+?\\\\]$',\n        relevance: 0\n      },\n      // quoteblocks\n      {\n        className: 'quote',\n        begin: '^_{4,}\\\\n',\n        end: '\\\\n_{4,}$',\n        relevance: 10\n      },\n      // listing and literal blocks\n      {\n        className: 'code',\n        begin: '^[\\\\-\\\\.]{4,}\\\\n',\n        end: '\\\\n[\\\\-\\\\.]{4,}$',\n        relevance: 10\n      },\n      // passthrough blocks\n      {\n        begin: '^\\\\+{4,}\\\\n',\n        end: '\\\\n\\\\+{4,}$',\n        contains: [{\n          begin: '<',\n          end: '>',\n          subLanguage: 'xml',\n          relevance: 0\n        }],\n        relevance: 10\n      },\n\n      BULLET_LIST,\n      ADMONITION,\n      ...ESCAPED_FORMATTING,\n      ...STRONG,\n      ...EMPHASIS,\n\n      // inline smart quotes\n      {\n        className: 'string',\n        variants: [\n          {\n            begin: \"``.+?''\"\n          },\n          {\n            begin: \"`.+?'\"\n          }\n        ]\n      },\n      // inline unconstrained emphasis\n      {\n        className: 'code',\n        begin: /`{2}/,\n        end: /(\\n{2}|`{2})/\n      },\n      // inline code snippets (TODO should get same treatment as strong and emphasis)\n      {\n        className: 'code',\n        begin: '(`.+?`|\\\\+.+?\\\\+)',\n        relevance: 0\n      },\n      // indented literal block\n      {\n        className: 'code',\n        begin: '^[ \\\\t]',\n        end: '$',\n        relevance: 0\n      },\n      HORIZONTAL_RULE,\n      // images and links\n      {\n        begin: '(link:)?(http|https|ftp|file|irc|image:?):\\\\S+?\\\\[[^[]*?\\\\]',\n        returnBegin: true,\n        contains: [\n          {\n            begin: '(link|image:?):',\n            relevance: 0\n          },\n          {\n            className: 'link',\n            begin: '\\\\w',\n            end: '[^\\\\[]+',\n            relevance: 0\n          },\n          {\n            className: 'string',\n            begin: '\\\\[',\n            end: '\\\\]',\n            excludeBegin: true,\n            excludeEnd: true,\n            relevance: 0\n          }\n        ],\n        relevance: 10\n      }\n    ]\n  };\n}\n\nmodule.exports = asciidoc;\n","/**\n * @param {string} value\n * @returns {RegExp}\n * */\n\n/**\n * @param {RegExp | string } re\n * @returns {string}\n */\nfunction source(re) {\n  if (!re) return null;\n  if (typeof re === \"string\") return re;\n\n  return re.source;\n}\n\n/**\n * @param {...(RegExp | string) } args\n * @returns {string}\n */\nfunction concat(...args) {\n  const joined = args.map((x) => source(x)).join(\"\");\n  return joined;\n}\n\n/*\nLanguage: Bash\nAuthor: vah \nContributrors: Benjamin Pannell \nWebsite: https://www.gnu.org/software/bash/\nCategory: common\n*/\n\n/** @type LanguageFn */\nfunction bash(hljs) {\n  const VAR = {};\n  const BRACED_VAR = {\n    begin: /\\$\\{/,\n    end:/\\}/,\n    contains: [\n      \"self\",\n      {\n        begin: /:-/,\n        contains: [ VAR ]\n      } // default values\n    ]\n  };\n  Object.assign(VAR,{\n    className: 'variable',\n    variants: [\n      {begin: concat(/\\$[\\w\\d#@][\\w\\d_]*/,\n        // negative look-ahead tries to avoid matching patterns that are not\n        // Perl at all like $ident$, @ident@, etc.\n        `(?![\\\\w\\\\d])(?![$])`) },\n      BRACED_VAR\n    ]\n  });\n\n  const SUBST = {\n    className: 'subst',\n    begin: /\\$\\(/, end: /\\)/,\n    contains: [hljs.BACKSLASH_ESCAPE]\n  };\n  const HERE_DOC = {\n    begin: /<<-?\\s*(?=\\w+)/,\n    starts: {\n      contains: [\n        hljs.END_SAME_AS_BEGIN({\n          begin: /(\\w+)/,\n          end: /(\\w+)/,\n          className: 'string'\n        })\n      ]\n    }\n  };\n  const QUOTE_STRING = {\n    className: 'string',\n    begin: /\"/, end: /\"/,\n    contains: [\n      hljs.BACKSLASH_ESCAPE,\n      VAR,\n      SUBST\n    ]\n  };\n  SUBST.contains.push(QUOTE_STRING);\n  const ESCAPED_QUOTE = {\n    className: '',\n    begin: /\\\\\"/\n\n  };\n  const APOS_STRING = {\n    className: 'string',\n    begin: /'/, end: /'/\n  };\n  const ARITHMETIC = {\n    begin: /\\$\\(\\(/,\n    end: /\\)\\)/,\n    contains: [\n      { begin: /\\d+#[0-9a-f]+/, className: \"number\" },\n      hljs.NUMBER_MODE,\n      VAR\n    ]\n  };\n  const SH_LIKE_SHELLS = [\n    \"fish\",\n    \"bash\",\n    \"zsh\",\n    \"sh\",\n    \"csh\",\n    \"ksh\",\n    \"tcsh\",\n    \"dash\",\n    \"scsh\",\n  ];\n  const KNOWN_SHEBANG = hljs.SHEBANG({\n    binary: `(${SH_LIKE_SHELLS.join(\"|\")})`,\n    relevance: 10\n  });\n  const FUNCTION = {\n    className: 'function',\n    begin: /\\w[\\w\\d_]*\\s*\\(\\s*\\)\\s*\\{/,\n    returnBegin: true,\n    contains: [hljs.inherit(hljs.TITLE_MODE, {begin: /\\w[\\w\\d_]*/})],\n    relevance: 0\n  };\n\n  return {\n    name: 'Bash',\n    aliases: ['sh', 'zsh'],\n    keywords: {\n      $pattern: /\\b[a-z._-]+\\b/,\n      keyword:\n        'if then else elif fi for while in do done case esac function',\n      literal:\n        'true false',\n      built_in:\n        // Shell built-ins\n        // http://www.gnu.org/software/bash/manual/html_node/Shell-Builtin-Commands.html\n        'break cd continue eval exec exit export getopts hash pwd readonly return shift test times ' +\n        'trap umask unset ' +\n        // Bash built-ins\n        'alias bind builtin caller command declare echo enable help let local logout mapfile printf ' +\n        'read readarray source type typeset ulimit unalias ' +\n        // Shell modifiers\n        'set shopt ' +\n        // Zsh built-ins\n        'autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles ' +\n        'compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate ' +\n        'fc fg float functions getcap getln history integer jobs kill limit log noglob popd print ' +\n        'pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit ' +\n        'unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof ' +\n        'zpty zregexparse zsocket zstyle ztcp'\n    },\n    contains: [\n      KNOWN_SHEBANG, // to catch known shells and boost relevancy\n      hljs.SHEBANG(), // to catch unknown shells but still highlight the shebang\n      FUNCTION,\n      ARITHMETIC,\n      hljs.HASH_COMMENT_MODE,\n      HERE_DOC,\n      QUOTE_STRING,\n      ESCAPED_QUOTE,\n      APOS_STRING,\n      VAR\n    ]\n  };\n}\n\nmodule.exports = bash;\n","const MODES = (hljs) => {\n  return {\n    IMPORTANT: {\n      className: 'meta',\n      begin: '!important'\n    },\n    HEXCOLOR: {\n      className: 'number',\n      begin: '#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})'\n    },\n    ATTRIBUTE_SELECTOR_MODE: {\n      className: 'selector-attr',\n      begin: /\\[/,\n      end: /\\]/,\n      illegal: '$',\n      contains: [\n        hljs.APOS_STRING_MODE,\n        hljs.QUOTE_STRING_MODE\n      ]\n    }\n  };\n};\n\nconst TAGS = [\n  'a',\n  'abbr',\n  'address',\n  'article',\n  'aside',\n  'audio',\n  'b',\n  'blockquote',\n  'body',\n  'button',\n  'canvas',\n  'caption',\n  'cite',\n  'code',\n  'dd',\n  'del',\n  'details',\n  'dfn',\n  'div',\n  'dl',\n  'dt',\n  'em',\n  'fieldset',\n  'figcaption',\n  'figure',\n  'footer',\n  'form',\n  'h1',\n  'h2',\n  'h3',\n  'h4',\n  'h5',\n  'h6',\n  'header',\n  'hgroup',\n  'html',\n  'i',\n  'iframe',\n  'img',\n  'input',\n  'ins',\n  'kbd',\n  'label',\n  'legend',\n  'li',\n  'main',\n  'mark',\n  'menu',\n  'nav',\n  'object',\n  'ol',\n  'p',\n  'q',\n  'quote',\n  'samp',\n  'section',\n  'span',\n  'strong',\n  'summary',\n  'sup',\n  'table',\n  'tbody',\n  'td',\n  'textarea',\n  'tfoot',\n  'th',\n  'thead',\n  'time',\n  'tr',\n  'ul',\n  'var',\n  'video'\n];\n\nconst MEDIA_FEATURES = [\n  'any-hover',\n  'any-pointer',\n  'aspect-ratio',\n  'color',\n  'color-gamut',\n  'color-index',\n  'device-aspect-ratio',\n  'device-height',\n  'device-width',\n  'display-mode',\n  'forced-colors',\n  'grid',\n  'height',\n  'hover',\n  'inverted-colors',\n  'monochrome',\n  'orientation',\n  'overflow-block',\n  'overflow-inline',\n  'pointer',\n  'prefers-color-scheme',\n  'prefers-contrast',\n  'prefers-reduced-motion',\n  'prefers-reduced-transparency',\n  'resolution',\n  'scan',\n  'scripting',\n  'update',\n  'width',\n  // TODO: find a better solution?\n  'min-width',\n  'max-width',\n  'min-height',\n  'max-height'\n];\n\n// https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\nconst PSEUDO_CLASSES = [\n  'active',\n  'any-link',\n  'blank',\n  'checked',\n  'current',\n  'default',\n  'defined',\n  'dir', // dir()\n  'disabled',\n  'drop',\n  'empty',\n  'enabled',\n  'first',\n  'first-child',\n  'first-of-type',\n  'fullscreen',\n  'future',\n  'focus',\n  'focus-visible',\n  'focus-within',\n  'has', // has()\n  'host', // host or host()\n  'host-context', // host-context()\n  'hover',\n  'indeterminate',\n  'in-range',\n  'invalid',\n  'is', // is()\n  'lang', // lang()\n  'last-child',\n  'last-of-type',\n  'left',\n  'link',\n  'local-link',\n  'not', // not()\n  'nth-child', // nth-child()\n  'nth-col', // nth-col()\n  'nth-last-child', // nth-last-child()\n  'nth-last-col', // nth-last-col()\n  'nth-last-of-type', //nth-last-of-type()\n  'nth-of-type', //nth-of-type()\n  'only-child',\n  'only-of-type',\n  'optional',\n  'out-of-range',\n  'past',\n  'placeholder-shown',\n  'read-only',\n  'read-write',\n  'required',\n  'right',\n  'root',\n  'scope',\n  'target',\n  'target-within',\n  'user-invalid',\n  'valid',\n  'visited',\n  'where' // where()\n];\n\n// https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\nconst PSEUDO_ELEMENTS = [\n  'after',\n  'backdrop',\n  'before',\n  'cue',\n  'cue-region',\n  'first-letter',\n  'first-line',\n  'grammar-error',\n  'marker',\n  'part',\n  'placeholder',\n  'selection',\n  'slotted',\n  'spelling-error'\n];\n\nconst ATTRIBUTES = [\n  'align-content',\n  'align-items',\n  'align-self',\n  'animation',\n  'animation-delay',\n  'animation-direction',\n  'animation-duration',\n  'animation-fill-mode',\n  'animation-iteration-count',\n  'animation-name',\n  'animation-play-state',\n  'animation-timing-function',\n  'auto',\n  'backface-visibility',\n  'background',\n  'background-attachment',\n  'background-clip',\n  'background-color',\n  'background-image',\n  'background-origin',\n  'background-position',\n  'background-repeat',\n  'background-size',\n  'border',\n  'border-bottom',\n  'border-bottom-color',\n  'border-bottom-left-radius',\n  'border-bottom-right-radius',\n  'border-bottom-style',\n  'border-bottom-width',\n  'border-collapse',\n  'border-color',\n  'border-image',\n  'border-image-outset',\n  'border-image-repeat',\n  'border-image-slice',\n  'border-image-source',\n  'border-image-width',\n  'border-left',\n  'border-left-color',\n  'border-left-style',\n  'border-left-width',\n  'border-radius',\n  'border-right',\n  'border-right-color',\n  'border-right-style',\n  'border-right-width',\n  'border-spacing',\n  'border-style',\n  'border-top',\n  'border-top-color',\n  'border-top-left-radius',\n  'border-top-right-radius',\n  'border-top-style',\n  'border-top-width',\n  'border-width',\n  'bottom',\n  'box-decoration-break',\n  'box-shadow',\n  'box-sizing',\n  'break-after',\n  'break-before',\n  'break-inside',\n  'caption-side',\n  'clear',\n  'clip',\n  'clip-path',\n  'color',\n  'column-count',\n  'column-fill',\n  'column-gap',\n  'column-rule',\n  'column-rule-color',\n  'column-rule-style',\n  'column-rule-width',\n  'column-span',\n  'column-width',\n  'columns',\n  'content',\n  'counter-increment',\n  'counter-reset',\n  'cursor',\n  'direction',\n  'display',\n  'empty-cells',\n  'filter',\n  'flex',\n  'flex-basis',\n  'flex-direction',\n  'flex-flow',\n  'flex-grow',\n  'flex-shrink',\n  'flex-wrap',\n  'float',\n  'font',\n  'font-display',\n  'font-family',\n  'font-feature-settings',\n  'font-kerning',\n  'font-language-override',\n  'font-size',\n  'font-size-adjust',\n  'font-smoothing',\n  'font-stretch',\n  'font-style',\n  'font-variant',\n  'font-variant-ligatures',\n  'font-variation-settings',\n  'font-weight',\n  'height',\n  'hyphens',\n  'icon',\n  'image-orientation',\n  'image-rendering',\n  'image-resolution',\n  'ime-mode',\n  'inherit',\n  'initial',\n  'justify-content',\n  'left',\n  'letter-spacing',\n  'line-height',\n  'list-style',\n  'list-style-image',\n  'list-style-position',\n  'list-style-type',\n  'margin',\n  'margin-bottom',\n  'margin-left',\n  'margin-right',\n  'margin-top',\n  'marks',\n  'mask',\n  'max-height',\n  'max-width',\n  'min-height',\n  'min-width',\n  'nav-down',\n  'nav-index',\n  'nav-left',\n  'nav-right',\n  'nav-up',\n  'none',\n  'normal',\n  'object-fit',\n  'object-position',\n  'opacity',\n  'order',\n  'orphans',\n  'outline',\n  'outline-color',\n  'outline-offset',\n  'outline-style',\n  'outline-width',\n  'overflow',\n  'overflow-wrap',\n  'overflow-x',\n  'overflow-y',\n  'padding',\n  'padding-bottom',\n  'padding-left',\n  'padding-right',\n  'padding-top',\n  'page-break-after',\n  'page-break-before',\n  'page-break-inside',\n  'perspective',\n  'perspective-origin',\n  'pointer-events',\n  'position',\n  'quotes',\n  'resize',\n  'right',\n  'src', // @font-face\n  'tab-size',\n  'table-layout',\n  'text-align',\n  'text-align-last',\n  'text-decoration',\n  'text-decoration-color',\n  'text-decoration-line',\n  'text-decoration-style',\n  'text-indent',\n  'text-overflow',\n  'text-rendering',\n  'text-shadow',\n  'text-transform',\n  'text-underline-position',\n  'top',\n  'transform',\n  'transform-origin',\n  'transform-style',\n  'transition',\n  'transition-delay',\n  'transition-duration',\n  'transition-property',\n  'transition-timing-function',\n  'unicode-bidi',\n  'vertical-align',\n  'visibility',\n  'white-space',\n  'widows',\n  'width',\n  'word-break',\n  'word-spacing',\n  'word-wrap',\n  'z-index'\n  // reverse makes sure longer attributes `font-weight` are matched fully\n  // instead of getting false positives on say `font`\n].reverse();\n\n/**\n * @param {string} value\n * @returns {RegExp}\n * */\n\n/**\n * @param {RegExp | string } re\n * @returns {string}\n */\nfunction source(re) {\n  if (!re) return null;\n  if (typeof re === \"string\") return re;\n\n  return re.source;\n}\n\n/**\n * @param {RegExp | string } re\n * @returns {string}\n */\nfunction lookahead(re) {\n  return concat('(?=', re, ')');\n}\n\n/**\n * @param {...(RegExp | string) } args\n * @returns {string}\n */\nfunction concat(...args) {\n  const joined = args.map((x) => source(x)).join(\"\");\n  return joined;\n}\n\n/*\nLanguage: CSS\nCategory: common, css\nWebsite: https://developer.mozilla.org/en-US/docs/Web/CSS\n*/\n\n/** @type LanguageFn */\nfunction css(hljs) {\n  const modes = MODES(hljs);\n  const FUNCTION_DISPATCH = {\n    className: \"built_in\",\n    begin: /[\\w-]+(?=\\()/\n  };\n  const VENDOR_PREFIX = {\n    begin: /-(webkit|moz|ms|o)-(?=[a-z])/\n  };\n  const AT_MODIFIERS = \"and or not only\";\n  const AT_PROPERTY_RE = /@-?\\w[\\w]*(-\\w+)*/; // @-webkit-keyframes\n  const IDENT_RE = '[a-zA-Z-][a-zA-Z0-9_-]*';\n  const STRINGS = [\n    hljs.APOS_STRING_MODE,\n    hljs.QUOTE_STRING_MODE\n  ];\n\n  return {\n    name: 'CSS',\n    case_insensitive: true,\n    illegal: /[=|'\\$]/,\n    keywords: {\n      keyframePosition: \"from to\"\n    },\n    classNameAliases: {\n      // for visual continuity with `tag {}` and because we\n      // don't have a great class for this?\n      keyframePosition: \"selector-tag\"\n    },\n    contains: [\n      hljs.C_BLOCK_COMMENT_MODE,\n      VENDOR_PREFIX,\n      // to recognize keyframe 40% etc which are outside the scope of our\n      // attribute value mode\n      hljs.CSS_NUMBER_MODE,\n      {\n        className: 'selector-id',\n        begin: /#[A-Za-z0-9_-]+/,\n        relevance: 0\n      },\n      {\n        className: 'selector-class',\n        begin: '\\\\.' + IDENT_RE,\n        relevance: 0\n      },\n      modes.ATTRIBUTE_SELECTOR_MODE,\n      {\n        className: 'selector-pseudo',\n        variants: [\n          {\n            begin: ':(' + PSEUDO_CLASSES.join('|') + ')'\n          },\n          {\n            begin: '::(' + PSEUDO_ELEMENTS.join('|') + ')'\n          }\n        ]\n      },\n      // we may actually need this (12/2020)\n      // { // pseudo-selector params\n      //   begin: /\\(/,\n      //   end: /\\)/,\n      //   contains: [ hljs.CSS_NUMBER_MODE ]\n      // },\n      {\n        className: 'attribute',\n        begin: '\\\\b(' + ATTRIBUTES.join('|') + ')\\\\b'\n      },\n      // attribute values\n      {\n        begin: ':',\n        end: '[;}]',\n        contains: [\n          modes.HEXCOLOR,\n          modes.IMPORTANT,\n          hljs.CSS_NUMBER_MODE,\n          ...STRINGS,\n          // needed to highlight these as strings and to avoid issues with\n          // illegal characters that might be inside urls that would tigger the\n          // languages illegal stack\n          {\n            begin: /(url|data-uri)\\(/,\n            end: /\\)/,\n            relevance: 0, // from keywords\n            keywords: {\n              built_in: \"url data-uri\"\n            },\n            contains: [\n              {\n                className: \"string\",\n                // any character other than `)` as in `url()` will be the start\n                // of a string, which ends with `)` (from the parent mode)\n                begin: /[^)]/,\n                endsWithParent: true,\n                excludeEnd: true\n              }\n            ]\n          },\n          FUNCTION_DISPATCH\n        ]\n      },\n      {\n        begin: lookahead(/@/),\n        end: '[{;]',\n        relevance: 0,\n        illegal: /:/, // break on Less variables @var: ...\n        contains: [\n          {\n            className: 'keyword',\n            begin: AT_PROPERTY_RE\n          },\n          {\n            begin: /\\s/,\n            endsWithParent: true,\n            excludeEnd: true,\n            relevance: 0,\n            keywords: {\n              $pattern: /[a-z-]+/,\n              keyword: AT_MODIFIERS,\n              attribute: MEDIA_FEATURES.join(\" \")\n            },\n            contains: [\n              {\n                begin: /[a-z-]+(?=:)/,\n                className: \"attribute\"\n              },\n              ...STRINGS,\n              hljs.CSS_NUMBER_MODE\n            ]\n          }\n        ]\n      },\n      {\n        className: 'selector-tag',\n        begin: '\\\\b(' + TAGS.join('|') + ')\\\\b'\n      }\n    ]\n  };\n}\n\nmodule.exports = css;\n","/*\nLanguage: Diff\nDescription: Unified and context diff\nAuthor: Vasily Polovnyov \nWebsite: https://www.gnu.org/software/diffutils/\nCategory: common\n*/\n\n/** @type LanguageFn */\nfunction diff(hljs) {\n  return {\n    name: 'Diff',\n    aliases: ['patch'],\n    contains: [\n      {\n        className: 'meta',\n        relevance: 10,\n        variants: [\n          {\n            begin: /^@@ +-\\d+,\\d+ +\\+\\d+,\\d+ +@@/\n          },\n          {\n            begin: /^\\*\\*\\* +\\d+,\\d+ +\\*\\*\\*\\*$/\n          },\n          {\n            begin: /^--- +\\d+,\\d+ +----$/\n          }\n        ]\n      },\n      {\n        className: 'comment',\n        variants: [\n          {\n            begin: /Index: /,\n            end: /$/\n          },\n          {\n            begin: /^index/,\n            end: /$/\n          },\n          {\n            begin: /={3,}/,\n            end: /$/\n          },\n          {\n            begin: /^-{3}/,\n            end: /$/\n          },\n          {\n            begin: /^\\*{3} /,\n            end: /$/\n          },\n          {\n            begin: /^\\+{3}/,\n            end: /$/\n          },\n          {\n            begin: /^\\*{15}$/\n          },\n          {\n            begin: /^diff --git/,\n            end: /$/\n          }\n        ]\n      },\n      {\n        className: 'addition',\n        begin: /^\\+/,\n        end: /$/\n      },\n      {\n        className: 'deletion',\n        begin: /^-/,\n        end: /$/\n      },\n      {\n        className: 'addition',\n        begin: /^!/,\n        end: /$/\n      }\n    ]\n  };\n}\n\nmodule.exports = diff;\n","/*\nLanguage: Dockerfile\nRequires: bash.js\nAuthor: Alexis Hénaut \nDescription: language definition for Dockerfile files\nWebsite: https://docs.docker.com/engine/reference/builder/\nCategory: config\n*/\n\n/** @type LanguageFn */\nfunction dockerfile(hljs) {\n  return {\n    name: 'Dockerfile',\n    aliases: ['docker'],\n    case_insensitive: true,\n    keywords: 'from maintainer expose env arg user onbuild stopsignal',\n    contains: [\n      hljs.HASH_COMMENT_MODE,\n      hljs.APOS_STRING_MODE,\n      hljs.QUOTE_STRING_MODE,\n      hljs.NUMBER_MODE,\n      {\n        beginKeywords: 'run cmd entrypoint volume add copy workdir label healthcheck shell',\n        starts: {\n          end: /[^\\\\]$/,\n          subLanguage: 'bash'\n        }\n      }\n    ],\n    illegal: '\nContributors: Anton Kochkov \nWebsite: https://en.wikipedia.org/wiki/Batch_file\n*/\n\n/** @type LanguageFn */\nfunction dos(hljs) {\n  const COMMENT = hljs.COMMENT(\n    /^\\s*@?rem\\b/, /$/,\n    {\n      relevance: 10\n    }\n  );\n  const LABEL = {\n    className: 'symbol',\n    begin: '^\\\\s*[A-Za-z._?][A-Za-z0-9_$#@~.?]*(:|\\\\s+label)',\n    relevance: 0\n  };\n  return {\n    name: 'Batch file (DOS)',\n    aliases: [\n      'bat',\n      'cmd'\n    ],\n    case_insensitive: true,\n    illegal: /\\/\\*/,\n    keywords: {\n      keyword:\n        'if else goto for in do call exit not exist errorlevel defined ' +\n        'equ neq lss leq gtr geq',\n      built_in:\n        'prn nul lpt3 lpt2 lpt1 con com4 com3 com2 com1 aux ' +\n        'shift cd dir echo setlocal endlocal set pause copy ' +\n        'append assoc at attrib break cacls cd chcp chdir chkdsk chkntfs cls cmd color ' +\n        'comp compact convert date dir diskcomp diskcopy doskey erase fs ' +\n        'find findstr format ftype graftabl help keyb label md mkdir mode more move path ' +\n        'pause print popd pushd promt rd recover rem rename replace restore rmdir shift ' +\n        'sort start subst time title tree type ver verify vol ' +\n        // winutils\n        'ping net ipconfig taskkill xcopy ren del'\n    },\n    contains: [\n      {\n        className: 'variable',\n        begin: /%%[^ ]|%[^ ]+?%|![^ ]+?!/\n      },\n      {\n        className: 'function',\n        begin: LABEL.begin,\n        end: 'goto:eof',\n        contains: [\n          hljs.inherit(hljs.TITLE_MODE, {\n            begin: '([_a-zA-Z]\\\\w*\\\\.)*([_a-zA-Z]\\\\w*:)?[_a-zA-Z]\\\\w*'\n          }),\n          COMMENT\n        ]\n      },\n      {\n        className: 'number',\n        begin: '\\\\b\\\\d+',\n        relevance: 0\n      },\n      COMMENT\n    ]\n  };\n}\n\nmodule.exports = dos;\n","/*\nLanguage: Gradle\nDescription: Gradle is an open-source build automation tool focused on flexibility and performance.\nWebsite: https://gradle.org\nAuthor: Damian Mee \n*/\n\nfunction gradle(hljs) {\n  return {\n    name: 'Gradle',\n    case_insensitive: true,\n    keywords: {\n      keyword:\n        'task project allprojects subprojects artifacts buildscript configurations ' +\n        'dependencies repositories sourceSets description delete from into include ' +\n        'exclude source classpath destinationDir includes options sourceCompatibility ' +\n        'targetCompatibility group flatDir doLast doFirst flatten todir fromdir ant ' +\n        'def abstract break case catch continue default do else extends final finally ' +\n        'for if implements instanceof native new private protected public return static ' +\n        'switch synchronized throw throws transient try volatile while strictfp package ' +\n        'import false null super this true antlrtask checkstyle codenarc copy boolean ' +\n        'byte char class double float int interface long short void compile runTime ' +\n        'file fileTree abs any append asList asWritable call collect compareTo count ' +\n        'div dump each eachByte eachFile eachLine every find findAll flatten getAt ' +\n        'getErr getIn getOut getText grep immutable inject inspect intersect invokeMethods ' +\n        'isCase join leftShift minus multiply newInputStream newOutputStream newPrintWriter ' +\n        'newReader newWriter next plus pop power previous print println push putAt read ' +\n        'readBytes readLines reverse reverseEach round size sort splitEachLine step subMap ' +\n        'times toInteger toList tokenize upto waitForOrKill withPrintWriter withReader ' +\n        'withStream withWriter withWriterAppend write writeLine'\n    },\n    contains: [\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      hljs.APOS_STRING_MODE,\n      hljs.QUOTE_STRING_MODE,\n      hljs.NUMBER_MODE,\n      hljs.REGEXP_MODE\n\n    ]\n  };\n}\n\nmodule.exports = gradle;\n","/**\n * @param {string} value\n * @returns {RegExp}\n * */\n\n/**\n * @param {RegExp | string } re\n * @returns {string}\n */\nfunction source(re) {\n  if (!re) return null;\n  if (typeof re === \"string\") return re;\n\n  return re.source;\n}\n\n/**\n * @param {RegExp | string } re\n * @returns {string}\n */\nfunction lookahead(re) {\n  return concat('(?=', re, ')');\n}\n\n/**\n * @param {...(RegExp | string) } args\n * @returns {string}\n */\nfunction concat(...args) {\n  const joined = args.map((x) => source(x)).join(\"\");\n  return joined;\n}\n\n/*\n Language: Groovy\n Author: Guillaume Laforge \n Description: Groovy programming language implementation inspired from Vsevolod's Java mode\n Website: https://groovy-lang.org\n */\n\nfunction variants(variants, obj = {}) {\n  obj.variants = variants;\n  return obj;\n}\n\nfunction groovy(hljs) {\n  const IDENT_RE = '[A-Za-z0-9_$]+';\n  const COMMENT = variants([\n    hljs.C_LINE_COMMENT_MODE,\n    hljs.C_BLOCK_COMMENT_MODE,\n    hljs.COMMENT(\n      '/\\\\*\\\\*',\n      '\\\\*/',\n      {\n        relevance: 0,\n        contains: [\n          {\n            // eat up @'s in emails to prevent them to be recognized as doctags\n            begin: /\\w+@/,\n            relevance: 0\n          },\n          {\n            className: 'doctag',\n            begin: '@[A-Za-z]+'\n          }\n        ]\n      }\n    )\n  ]);\n  const REGEXP = {\n    className: 'regexp',\n    begin: /~?\\/[^\\/\\n]+\\//,\n    contains: [ hljs.BACKSLASH_ESCAPE ]\n  };\n  const NUMBER = variants([\n    hljs.BINARY_NUMBER_MODE,\n    hljs.C_NUMBER_MODE\n  ]);\n  const STRING = variants([\n    {\n      begin: /\"\"\"/,\n      end: /\"\"\"/\n    },\n    {\n      begin: /'''/,\n      end: /'''/\n    },\n    {\n      begin: \"\\\\$/\",\n      end: \"/\\\\$\",\n      relevance: 10\n    },\n    hljs.APOS_STRING_MODE,\n    hljs.QUOTE_STRING_MODE\n  ],\n  {\n    className: \"string\"\n  }\n  );\n\n  return {\n    name: 'Groovy',\n    keywords: {\n      built_in: 'this super',\n      literal: 'true false null',\n      keyword:\n            'byte short char int long boolean float double void ' +\n            // groovy specific keywords\n            'def as in assert trait ' +\n            // common keywords with Java\n            'abstract static volatile transient public private protected synchronized final ' +\n            'class interface enum if else for while switch case break default continue ' +\n            'throw throws try catch finally implements extends new import package return instanceof'\n    },\n    contains: [\n      hljs.SHEBANG({\n        binary: \"groovy\",\n        relevance: 10\n      }),\n      COMMENT,\n      STRING,\n      REGEXP,\n      NUMBER,\n      {\n        className: 'class',\n        beginKeywords: 'class interface trait enum',\n        end: /\\{/,\n        illegal: ':',\n        contains: [\n          {\n            beginKeywords: 'extends implements'\n          },\n          hljs.UNDERSCORE_TITLE_MODE\n        ]\n      },\n      {\n        className: 'meta',\n        begin: '@[A-Za-z]+',\n        relevance: 0\n      },\n      {\n        // highlight map keys and named parameters as attrs\n        className: 'attr',\n        begin: IDENT_RE + '[ \\t]*:',\n        relevance: 0\n      },\n      {\n        // catch middle element of the ternary operator\n        // to avoid highlight it as a label, named parameter, or map key\n        begin: /\\?/,\n        end: /:/,\n        relevance: 0,\n        contains: [\n          COMMENT,\n          STRING,\n          REGEXP,\n          NUMBER,\n          'self'\n        ]\n      },\n      {\n        // highlight labeled statements\n        className: 'symbol',\n        begin: '^[ \\t]*' + lookahead(IDENT_RE + ':'),\n        excludeBegin: true,\n        end: IDENT_RE + ':',\n        relevance: 0\n      }\n    ],\n    illegal: /#|<\\//\n  };\n}\n\nmodule.exports = groovy;\n","/**\n * @param {string} value\n * @returns {RegExp}\n * */\n\n/**\n * @param {RegExp | string } re\n * @returns {string}\n */\nfunction source(re) {\n  if (!re) return null;\n  if (typeof re === \"string\") return re;\n\n  return re.source;\n}\n\n/**\n * @param {...(RegExp | string) } args\n * @returns {string}\n */\nfunction concat(...args) {\n  const joined = args.map((x) => source(x)).join(\"\");\n  return joined;\n}\n\n/*\nLanguage: HTTP\nDescription: HTTP request and response headers with automatic body highlighting\nAuthor: Ivan Sagalaev \nCategory: common, protocols\nWebsite: https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview\n*/\n\nfunction http(hljs) {\n  const VERSION = 'HTTP/(2|1\\\\.[01])';\n  const HEADER_NAME = /[A-Za-z][A-Za-z0-9-]*/;\n  const HEADER = {\n    className: 'attribute',\n    begin: concat('^', HEADER_NAME, '(?=\\\\:\\\\s)'),\n    starts: {\n      contains: [\n        {\n          className: \"punctuation\",\n          begin: /: /,\n          relevance: 0,\n          starts: {\n            end: '$',\n            relevance: 0\n          }\n        }\n      ]\n    }\n  };\n  const HEADERS_AND_BODY = [\n    HEADER,\n    {\n      begin: '\\\\n\\\\n',\n      starts: { subLanguage: [], endsWithParent: true }\n    }\n  ];\n\n  return {\n    name: 'HTTP',\n    aliases: ['https'],\n    illegal: /\\S/,\n    contains: [\n      // response\n      {\n        begin: '^(?=' + VERSION + \" \\\\d{3})\",\n        end: /$/,\n        contains: [\n          {\n            className: \"meta\",\n            begin: VERSION\n          },\n          {\n            className: 'number', begin: '\\\\b\\\\d{3}\\\\b'\n          }\n        ],\n        starts: {\n          end: /\\b\\B/,\n          illegal: /\\S/,\n          contains: HEADERS_AND_BODY\n        }\n      },\n      // request\n      {\n        begin: '(?=^[A-Z]+ (.*?) ' + VERSION + '$)',\n        end: /$/,\n        contains: [\n          {\n            className: 'string',\n            begin: ' ',\n            end: ' ',\n            excludeBegin: true,\n            excludeEnd: true\n          },\n          {\n            className: \"meta\",\n            begin: VERSION\n          },\n          {\n            className: 'keyword',\n            begin: '[A-Z]+'\n          }\n        ],\n        starts: {\n          end: /\\b\\B/,\n          illegal: /\\S/,\n          contains: HEADERS_AND_BODY\n        }\n      },\n      // to allow headers to work even without a preamble\n      hljs.inherit(HEADER, {\n        relevance: 0\n      })\n    ]\n  };\n}\n\nmodule.exports = http;\n","// https://docs.oracle.com/javase/specs/jls/se15/html/jls-3.html#jls-3.10\nvar decimalDigits = '[0-9](_*[0-9])*';\nvar frac = `\\\\.(${decimalDigits})`;\nvar hexDigits = '[0-9a-fA-F](_*[0-9a-fA-F])*';\nvar NUMERIC = {\n  className: 'number',\n  variants: [\n    // DecimalFloatingPointLiteral\n    // including ExponentPart\n    { begin: `(\\\\b(${decimalDigits})((${frac})|\\\\.)?|(${frac}))` +\n      `[eE][+-]?(${decimalDigits})[fFdD]?\\\\b` },\n    // excluding ExponentPart\n    { begin: `\\\\b(${decimalDigits})((${frac})[fFdD]?\\\\b|\\\\.([fFdD]\\\\b)?)` },\n    { begin: `(${frac})[fFdD]?\\\\b` },\n    { begin: `\\\\b(${decimalDigits})[fFdD]\\\\b` },\n\n    // HexadecimalFloatingPointLiteral\n    { begin: `\\\\b0[xX]((${hexDigits})\\\\.?|(${hexDigits})?\\\\.(${hexDigits}))` +\n      `[pP][+-]?(${decimalDigits})[fFdD]?\\\\b` },\n\n    // DecimalIntegerLiteral\n    { begin: '\\\\b(0|[1-9](_*[0-9])*)[lL]?\\\\b' },\n\n    // HexIntegerLiteral\n    { begin: `\\\\b0[xX](${hexDigits})[lL]?\\\\b` },\n\n    // OctalIntegerLiteral\n    { begin: '\\\\b0(_*[0-7])*[lL]?\\\\b' },\n\n    // BinaryIntegerLiteral\n    { begin: '\\\\b0[bB][01](_*[01])*[lL]?\\\\b' },\n  ],\n  relevance: 0\n};\n\n/*\nLanguage: Java\nAuthor: Vsevolod Solovyov \nCategory: common, enterprise\nWebsite: https://www.java.com/\n*/\n\nfunction java(hljs) {\n  var JAVA_IDENT_RE = '[\\u00C0-\\u02B8a-zA-Z_$][\\u00C0-\\u02B8a-zA-Z_$0-9]*';\n  var GENERIC_IDENT_RE = JAVA_IDENT_RE + '(<' + JAVA_IDENT_RE + '(\\\\s*,\\\\s*' + JAVA_IDENT_RE + ')*>)?';\n  var KEYWORDS = 'false synchronized int abstract float private char boolean var static null if const ' +\n    'for true while long strictfp finally protected import native final void ' +\n    'enum else break transient catch instanceof byte super volatile case assert short ' +\n    'package default double public try this switch continue throws protected public private ' +\n    'module requires exports do';\n\n  var ANNOTATION = {\n    className: 'meta',\n    begin: '@' + JAVA_IDENT_RE,\n    contains: [\n      {\n        begin: /\\(/,\n        end: /\\)/,\n        contains: [\"self\"] // allow nested () inside our annotation\n      },\n    ]\n  };\n  const NUMBER = NUMERIC;\n\n  return {\n    name: 'Java',\n    aliases: ['jsp'],\n    keywords: KEYWORDS,\n    illegal: /<\\/|#/,\n    contains: [\n      hljs.COMMENT(\n        '/\\\\*\\\\*',\n        '\\\\*/',\n        {\n          relevance: 0,\n          contains: [\n            {\n              // eat up @'s in emails to prevent them to be recognized as doctags\n              begin: /\\w+@/, relevance: 0\n            },\n            {\n              className: 'doctag',\n              begin: '@[A-Za-z]+'\n            }\n          ]\n        }\n      ),\n      // relevance boost\n      {\n        begin: /import java\\.[a-z]+\\./,\n        keywords: \"import\",\n        relevance: 2\n      },\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      hljs.APOS_STRING_MODE,\n      hljs.QUOTE_STRING_MODE,\n      {\n        className: 'class',\n        beginKeywords: 'class interface enum', end: /[{;=]/, excludeEnd: true,\n        // TODO: can this be removed somehow?\n        // an extra boost because Java is more popular than other languages with\n        // this same syntax feature (this is just to preserve our tests passing\n        // for now)\n        relevance: 1,\n        keywords: 'class interface enum',\n        illegal: /[:\"\\[\\]]/,\n        contains: [\n          { beginKeywords: 'extends implements' },\n          hljs.UNDERSCORE_TITLE_MODE\n        ]\n      },\n      {\n        // Expression keywords prevent 'keyword Name(...)' from being\n        // recognized as a function definition\n        beginKeywords: 'new throw return else',\n        relevance: 0\n      },\n      {\n        className: 'class',\n        begin: 'record\\\\s+' + hljs.UNDERSCORE_IDENT_RE + '\\\\s*\\\\(',\n        returnBegin: true,\n        excludeEnd: true,\n        end: /[{;=]/,\n        keywords: KEYWORDS,\n        contains: [\n          { beginKeywords: \"record\" },\n          {\n            begin: hljs.UNDERSCORE_IDENT_RE + '\\\\s*\\\\(',\n            returnBegin: true,\n            relevance: 0,\n            contains: [hljs.UNDERSCORE_TITLE_MODE]\n          },\n          {\n            className: 'params',\n            begin: /\\(/, end: /\\)/,\n            keywords: KEYWORDS,\n            relevance: 0,\n            contains: [\n              hljs.C_BLOCK_COMMENT_MODE\n            ]\n          },\n          hljs.C_LINE_COMMENT_MODE,\n          hljs.C_BLOCK_COMMENT_MODE\n        ]\n      },\n      {\n        className: 'function',\n        begin: '(' + GENERIC_IDENT_RE + '\\\\s+)+' + hljs.UNDERSCORE_IDENT_RE + '\\\\s*\\\\(', returnBegin: true, end: /[{;=]/,\n        excludeEnd: true,\n        keywords: KEYWORDS,\n        contains: [\n          {\n            begin: hljs.UNDERSCORE_IDENT_RE + '\\\\s*\\\\(', returnBegin: true,\n            relevance: 0,\n            contains: [hljs.UNDERSCORE_TITLE_MODE]\n          },\n          {\n            className: 'params',\n            begin: /\\(/, end: /\\)/,\n            keywords: KEYWORDS,\n            relevance: 0,\n            contains: [\n              ANNOTATION,\n              hljs.APOS_STRING_MODE,\n              hljs.QUOTE_STRING_MODE,\n              NUMBER,\n              hljs.C_BLOCK_COMMENT_MODE\n            ]\n          },\n          hljs.C_LINE_COMMENT_MODE,\n          hljs.C_BLOCK_COMMENT_MODE\n        ]\n      },\n      NUMBER,\n      ANNOTATION\n    ]\n  };\n}\n\nmodule.exports = java;\n","const IDENT_RE = '[A-Za-z$_][0-9A-Za-z$_]*';\nconst KEYWORDS = [\n  \"as\", // for exports\n  \"in\",\n  \"of\",\n  \"if\",\n  \"for\",\n  \"while\",\n  \"finally\",\n  \"var\",\n  \"new\",\n  \"function\",\n  \"do\",\n  \"return\",\n  \"void\",\n  \"else\",\n  \"break\",\n  \"catch\",\n  \"instanceof\",\n  \"with\",\n  \"throw\",\n  \"case\",\n  \"default\",\n  \"try\",\n  \"switch\",\n  \"continue\",\n  \"typeof\",\n  \"delete\",\n  \"let\",\n  \"yield\",\n  \"const\",\n  \"class\",\n  // JS handles these with a special rule\n  // \"get\",\n  // \"set\",\n  \"debugger\",\n  \"async\",\n  \"await\",\n  \"static\",\n  \"import\",\n  \"from\",\n  \"export\",\n  \"extends\"\n];\nconst LITERALS = [\n  \"true\",\n  \"false\",\n  \"null\",\n  \"undefined\",\n  \"NaN\",\n  \"Infinity\"\n];\n\nconst TYPES = [\n  \"Intl\",\n  \"DataView\",\n  \"Number\",\n  \"Math\",\n  \"Date\",\n  \"String\",\n  \"RegExp\",\n  \"Object\",\n  \"Function\",\n  \"Boolean\",\n  \"Error\",\n  \"Symbol\",\n  \"Set\",\n  \"Map\",\n  \"WeakSet\",\n  \"WeakMap\",\n  \"Proxy\",\n  \"Reflect\",\n  \"JSON\",\n  \"Promise\",\n  \"Float64Array\",\n  \"Int16Array\",\n  \"Int32Array\",\n  \"Int8Array\",\n  \"Uint16Array\",\n  \"Uint32Array\",\n  \"Float32Array\",\n  \"Array\",\n  \"Uint8Array\",\n  \"Uint8ClampedArray\",\n  \"ArrayBuffer\",\n  \"BigInt64Array\",\n  \"BigUint64Array\",\n  \"BigInt\"\n];\n\nconst ERROR_TYPES = [\n  \"EvalError\",\n  \"InternalError\",\n  \"RangeError\",\n  \"ReferenceError\",\n  \"SyntaxError\",\n  \"TypeError\",\n  \"URIError\"\n];\n\nconst BUILT_IN_GLOBALS = [\n  \"setInterval\",\n  \"setTimeout\",\n  \"clearInterval\",\n  \"clearTimeout\",\n\n  \"require\",\n  \"exports\",\n\n  \"eval\",\n  \"isFinite\",\n  \"isNaN\",\n  \"parseFloat\",\n  \"parseInt\",\n  \"decodeURI\",\n  \"decodeURIComponent\",\n  \"encodeURI\",\n  \"encodeURIComponent\",\n  \"escape\",\n  \"unescape\"\n];\n\nconst BUILT_IN_VARIABLES = [\n  \"arguments\",\n  \"this\",\n  \"super\",\n  \"console\",\n  \"window\",\n  \"document\",\n  \"localStorage\",\n  \"module\",\n  \"global\" // Node.js\n];\n\nconst BUILT_INS = [].concat(\n  BUILT_IN_GLOBALS,\n  BUILT_IN_VARIABLES,\n  TYPES,\n  ERROR_TYPES\n);\n\n/**\n * @param {string} value\n * @returns {RegExp}\n * */\n\n/**\n * @param {RegExp | string } re\n * @returns {string}\n */\nfunction source(re) {\n  if (!re) return null;\n  if (typeof re === \"string\") return re;\n\n  return re.source;\n}\n\n/**\n * @param {RegExp | string } re\n * @returns {string}\n */\nfunction lookahead(re) {\n  return concat('(?=', re, ')');\n}\n\n/**\n * @param {...(RegExp | string) } args\n * @returns {string}\n */\nfunction concat(...args) {\n  const joined = args.map((x) => source(x)).join(\"\");\n  return joined;\n}\n\n/*\nLanguage: JavaScript\nDescription: JavaScript (JS) is a lightweight, interpreted, or just-in-time compiled programming language with first-class functions.\nCategory: common, scripting\nWebsite: https://developer.mozilla.org/en-US/docs/Web/JavaScript\n*/\n\n/** @type LanguageFn */\nfunction javascript(hljs) {\n  /**\n   * Takes a string like \" {\n    const tag = \"',\n    end: ''\n  };\n  const XML_TAG = {\n    begin: /<[A-Za-z0-9\\\\._:-]+/,\n    end: /\\/[A-Za-z0-9\\\\._:-]+>|\\/>/,\n    /**\n     * @param {RegExpMatchArray} match\n     * @param {CallbackResponse} response\n     */\n    isTrulyOpeningTag: (match, response) => {\n      const afterMatchIndex = match[0].length + match.index;\n      const nextChar = match.input[afterMatchIndex];\n      // nested type?\n      // HTML should not include another raw `<` inside a tag\n      // But a type might: `>`, etc.\n      if (nextChar === \"<\") {\n        response.ignoreMatch();\n        return;\n      }\n      // \n      // This is now either a tag or a type.\n      if (nextChar === \">\") {\n        // if we cannot find a matching closing tag, then we\n        // will ignore it\n        if (!hasClosingTag(match, { after: afterMatchIndex })) {\n          response.ignoreMatch();\n        }\n      }\n    }\n  };\n  const KEYWORDS$1 = {\n    $pattern: IDENT_RE,\n    keyword: KEYWORDS,\n    literal: LITERALS,\n    built_in: BUILT_INS\n  };\n\n  // https://tc39.es/ecma262/#sec-literals-numeric-literals\n  const decimalDigits = '[0-9](_?[0-9])*';\n  const frac = `\\\\.(${decimalDigits})`;\n  // DecimalIntegerLiteral, including Annex B NonOctalDecimalIntegerLiteral\n  // https://tc39.es/ecma262/#sec-additional-syntax-numeric-literals\n  const decimalInteger = `0|[1-9](_?[0-9])*|0[0-7]*[89][0-9]*`;\n  const NUMBER = {\n    className: 'number',\n    variants: [\n      // DecimalLiteral\n      { begin: `(\\\\b(${decimalInteger})((${frac})|\\\\.)?|(${frac}))` +\n        `[eE][+-]?(${decimalDigits})\\\\b` },\n      { begin: `\\\\b(${decimalInteger})\\\\b((${frac})\\\\b|\\\\.)?|(${frac})\\\\b` },\n\n      // DecimalBigIntegerLiteral\n      { begin: `\\\\b(0|[1-9](_?[0-9])*)n\\\\b` },\n\n      // NonDecimalIntegerLiteral\n      { begin: \"\\\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*n?\\\\b\" },\n      { begin: \"\\\\b0[bB][0-1](_?[0-1])*n?\\\\b\" },\n      { begin: \"\\\\b0[oO][0-7](_?[0-7])*n?\\\\b\" },\n\n      // LegacyOctalIntegerLiteral (does not include underscore separators)\n      // https://tc39.es/ecma262/#sec-additional-syntax-numeric-literals\n      { begin: \"\\\\b0[0-7]+n?\\\\b\" },\n    ],\n    relevance: 0\n  };\n\n  const SUBST = {\n    className: 'subst',\n    begin: '\\\\$\\\\{',\n    end: '\\\\}',\n    keywords: KEYWORDS$1,\n    contains: [] // defined later\n  };\n  const HTML_TEMPLATE = {\n    begin: 'html`',\n    end: '',\n    starts: {\n      end: '`',\n      returnEnd: false,\n      contains: [\n        hljs.BACKSLASH_ESCAPE,\n        SUBST\n      ],\n      subLanguage: 'xml'\n    }\n  };\n  const CSS_TEMPLATE = {\n    begin: 'css`',\n    end: '',\n    starts: {\n      end: '`',\n      returnEnd: false,\n      contains: [\n        hljs.BACKSLASH_ESCAPE,\n        SUBST\n      ],\n      subLanguage: 'css'\n    }\n  };\n  const TEMPLATE_STRING = {\n    className: 'string',\n    begin: '`',\n    end: '`',\n    contains: [\n      hljs.BACKSLASH_ESCAPE,\n      SUBST\n    ]\n  };\n  const JSDOC_COMMENT = hljs.COMMENT(\n    /\\/\\*\\*(?!\\/)/,\n    '\\\\*/',\n    {\n      relevance: 0,\n      contains: [\n        {\n          className: 'doctag',\n          begin: '@[A-Za-z]+',\n          contains: [\n            {\n              className: 'type',\n              begin: '\\\\{',\n              end: '\\\\}',\n              relevance: 0\n            },\n            {\n              className: 'variable',\n              begin: IDENT_RE$1 + '(?=\\\\s*(-)|$)',\n              endsParent: true,\n              relevance: 0\n            },\n            // eat spaces (not newlines) so we can find\n            // types or variables\n            {\n              begin: /(?=[^\\n])\\s/,\n              relevance: 0\n            }\n          ]\n        }\n      ]\n    }\n  );\n  const COMMENT = {\n    className: \"comment\",\n    variants: [\n      JSDOC_COMMENT,\n      hljs.C_BLOCK_COMMENT_MODE,\n      hljs.C_LINE_COMMENT_MODE\n    ]\n  };\n  const SUBST_INTERNALS = [\n    hljs.APOS_STRING_MODE,\n    hljs.QUOTE_STRING_MODE,\n    HTML_TEMPLATE,\n    CSS_TEMPLATE,\n    TEMPLATE_STRING,\n    NUMBER,\n    hljs.REGEXP_MODE\n  ];\n  SUBST.contains = SUBST_INTERNALS\n    .concat({\n      // we need to pair up {} inside our subst to prevent\n      // it from ending too early by matching another }\n      begin: /\\{/,\n      end: /\\}/,\n      keywords: KEYWORDS$1,\n      contains: [\n        \"self\"\n      ].concat(SUBST_INTERNALS)\n    });\n  const SUBST_AND_COMMENTS = [].concat(COMMENT, SUBST.contains);\n  const PARAMS_CONTAINS = SUBST_AND_COMMENTS.concat([\n    // eat recursive parens in sub expressions\n    {\n      begin: /\\(/,\n      end: /\\)/,\n      keywords: KEYWORDS$1,\n      contains: [\"self\"].concat(SUBST_AND_COMMENTS)\n    }\n  ]);\n  const PARAMS = {\n    className: 'params',\n    begin: /\\(/,\n    end: /\\)/,\n    excludeBegin: true,\n    excludeEnd: true,\n    keywords: KEYWORDS$1,\n    contains: PARAMS_CONTAINS\n  };\n\n  return {\n    name: 'Javascript',\n    aliases: ['js', 'jsx', 'mjs', 'cjs'],\n    keywords: KEYWORDS$1,\n    // this will be extended by TypeScript\n    exports: { PARAMS_CONTAINS },\n    illegal: /#(?![$_A-z])/,\n    contains: [\n      hljs.SHEBANG({\n        label: \"shebang\",\n        binary: \"node\",\n        relevance: 5\n      }),\n      {\n        label: \"use_strict\",\n        className: 'meta',\n        relevance: 10,\n        begin: /^\\s*['\"]use (strict|asm)['\"]/\n      },\n      hljs.APOS_STRING_MODE,\n      hljs.QUOTE_STRING_MODE,\n      HTML_TEMPLATE,\n      CSS_TEMPLATE,\n      TEMPLATE_STRING,\n      COMMENT,\n      NUMBER,\n      { // object attr container\n        begin: concat(/[{,\\n]\\s*/,\n          // we need to look ahead to make sure that we actually have an\n          // attribute coming up so we don't steal a comma from a potential\n          // \"value\" container\n          //\n          // NOTE: this might not work how you think.  We don't actually always\n          // enter this mode and stay.  Instead it might merely match `,\n          // ` and then immediately end after the , because it\n          // fails to find any actual attrs. But this still does the job because\n          // it prevents the value contain rule from grabbing this instead and\n          // prevening this rule from firing when we actually DO have keys.\n          lookahead(concat(\n            // we also need to allow for multiple possible comments inbetween\n            // the first key:value pairing\n            /(((\\/\\/.*$)|(\\/\\*(\\*[^/]|[^*])*\\*\\/))\\s*)*/,\n            IDENT_RE$1 + '\\\\s*:'))),\n        relevance: 0,\n        contains: [\n          {\n            className: 'attr',\n            begin: IDENT_RE$1 + lookahead('\\\\s*:'),\n            relevance: 0\n          }\n        ]\n      },\n      { // \"value\" container\n        begin: '(' + hljs.RE_STARTERS_RE + '|\\\\b(case|return|throw)\\\\b)\\\\s*',\n        keywords: 'return throw case',\n        contains: [\n          COMMENT,\n          hljs.REGEXP_MODE,\n          {\n            className: 'function',\n            // we have to count the parens to make sure we actually have the\n            // correct bounding ( ) before the =>.  There could be any number of\n            // sub-expressions inside also surrounded by parens.\n            begin: '(\\\\(' +\n            '[^()]*(\\\\(' +\n            '[^()]*(\\\\(' +\n            '[^()]*' +\n            '\\\\)[^()]*)*' +\n            '\\\\)[^()]*)*' +\n            '\\\\)|' + hljs.UNDERSCORE_IDENT_RE + ')\\\\s*=>',\n            returnBegin: true,\n            end: '\\\\s*=>',\n            contains: [\n              {\n                className: 'params',\n                variants: [\n                  {\n                    begin: hljs.UNDERSCORE_IDENT_RE,\n                    relevance: 0\n                  },\n                  {\n                    className: null,\n                    begin: /\\(\\s*\\)/,\n                    skip: true\n                  },\n                  {\n                    begin: /\\(/,\n                    end: /\\)/,\n                    excludeBegin: true,\n                    excludeEnd: true,\n                    keywords: KEYWORDS$1,\n                    contains: PARAMS_CONTAINS\n                  }\n                ]\n              }\n            ]\n          },\n          { // could be a comma delimited list of params to a function call\n            begin: /,/, relevance: 0\n          },\n          {\n            className: '',\n            begin: /\\s/,\n            end: /\\s*/,\n            skip: true\n          },\n          { // JSX\n            variants: [\n              { begin: FRAGMENT.begin, end: FRAGMENT.end },\n              {\n                begin: XML_TAG.begin,\n                // we carefully check the opening tag to see if it truly\n                // is a tag and not a false positive\n                'on:begin': XML_TAG.isTrulyOpeningTag,\n                end: XML_TAG.end\n              }\n            ],\n            subLanguage: 'xml',\n            contains: [\n              {\n                begin: XML_TAG.begin,\n                end: XML_TAG.end,\n                skip: true,\n                contains: ['self']\n              }\n            ]\n          }\n        ],\n        relevance: 0\n      },\n      {\n        className: 'function',\n        beginKeywords: 'function',\n        end: /[{;]/,\n        excludeEnd: true,\n        keywords: KEYWORDS$1,\n        contains: [\n          'self',\n          hljs.inherit(hljs.TITLE_MODE, { begin: IDENT_RE$1 }),\n          PARAMS\n        ],\n        illegal: /%/\n      },\n      {\n        // prevent this from getting swallowed up by function\n        // since they appear \"function like\"\n        beginKeywords: \"while if switch catch for\"\n      },\n      {\n        className: 'function',\n        // we have to count the parens to make sure we actually have the correct\n        // bounding ( ).  There could be any number of sub-expressions inside\n        // also surrounded by parens.\n        begin: hljs.UNDERSCORE_IDENT_RE +\n          '\\\\(' + // first parens\n          '[^()]*(\\\\(' +\n            '[^()]*(\\\\(' +\n              '[^()]*' +\n            '\\\\)[^()]*)*' +\n          '\\\\)[^()]*)*' +\n          '\\\\)\\\\s*\\\\{', // end parens\n        returnBegin:true,\n        contains: [\n          PARAMS,\n          hljs.inherit(hljs.TITLE_MODE, { begin: IDENT_RE$1 }),\n        ]\n      },\n      // hack: prevents detection of keywords in some circumstances\n      // .keyword()\n      // $keyword = x\n      {\n        variants: [\n          { begin: '\\\\.' + IDENT_RE$1 },\n          { begin: '\\\\$' + IDENT_RE$1 }\n        ],\n        relevance: 0\n      },\n      { // ES6 class\n        className: 'class',\n        beginKeywords: 'class',\n        end: /[{;=]/,\n        excludeEnd: true,\n        illegal: /[:\"[\\]]/,\n        contains: [\n          { beginKeywords: 'extends' },\n          hljs.UNDERSCORE_TITLE_MODE\n        ]\n      },\n      {\n        begin: /\\b(?=constructor)/,\n        end: /[{;]/,\n        excludeEnd: true,\n        contains: [\n          hljs.inherit(hljs.TITLE_MODE, { begin: IDENT_RE$1 }),\n          'self',\n          PARAMS\n        ]\n      },\n      {\n        begin: '(get|set)\\\\s+(?=' + IDENT_RE$1 + '\\\\()',\n        end: /\\{/,\n        keywords: \"get set\",\n        contains: [\n          hljs.inherit(hljs.TITLE_MODE, { begin: IDENT_RE$1 }),\n          { begin: /\\(\\)/ }, // eat to avoid empty params\n          PARAMS\n        ]\n      },\n      {\n        begin: /\\$[(.]/ // relevance booster for a pattern common to JS libs: `$(something)` and `$.something`\n      }\n    ]\n  };\n}\n\nmodule.exports = javascript;\n","/*\nLanguage: JSON\nDescription: JSON (JavaScript Object Notation) is a lightweight data-interchange format.\nAuthor: Ivan Sagalaev \nWebsite: http://www.json.org\nCategory: common, protocols\n*/\n\nfunction json(hljs) {\n  const LITERALS = {\n    literal: 'true false null'\n  };\n  const ALLOWED_COMMENTS = [\n    hljs.C_LINE_COMMENT_MODE,\n    hljs.C_BLOCK_COMMENT_MODE\n  ];\n  const TYPES = [\n    hljs.QUOTE_STRING_MODE,\n    hljs.C_NUMBER_MODE\n  ];\n  const VALUE_CONTAINER = {\n    end: ',',\n    endsWithParent: true,\n    excludeEnd: true,\n    contains: TYPES,\n    keywords: LITERALS\n  };\n  const OBJECT = {\n    begin: /\\{/,\n    end: /\\}/,\n    contains: [\n      {\n        className: 'attr',\n        begin: /\"/,\n        end: /\"/,\n        contains: [hljs.BACKSLASH_ESCAPE],\n        illegal: '\\\\n'\n      },\n      hljs.inherit(VALUE_CONTAINER, {\n        begin: /:/\n      })\n    ].concat(ALLOWED_COMMENTS),\n    illegal: '\\\\S'\n  };\n  const ARRAY = {\n    begin: '\\\\[',\n    end: '\\\\]',\n    contains: [hljs.inherit(VALUE_CONTAINER)], // inherit is a workaround for a bug that makes shared modes with endsWithParent compile only the ending of one of the parents\n    illegal: '\\\\S'\n  };\n  TYPES.push(OBJECT, ARRAY);\n  ALLOWED_COMMENTS.forEach(function(rule) {\n    TYPES.push(rule);\n  });\n  return {\n    name: 'JSON',\n    contains: TYPES,\n    keywords: LITERALS,\n    illegal: '\\\\S'\n  };\n}\n\nmodule.exports = json;\n","// https://docs.oracle.com/javase/specs/jls/se15/html/jls-3.html#jls-3.10\nvar decimalDigits = '[0-9](_*[0-9])*';\nvar frac = `\\\\.(${decimalDigits})`;\nvar hexDigits = '[0-9a-fA-F](_*[0-9a-fA-F])*';\nvar NUMERIC = {\n  className: 'number',\n  variants: [\n    // DecimalFloatingPointLiteral\n    // including ExponentPart\n    { begin: `(\\\\b(${decimalDigits})((${frac})|\\\\.)?|(${frac}))` +\n      `[eE][+-]?(${decimalDigits})[fFdD]?\\\\b` },\n    // excluding ExponentPart\n    { begin: `\\\\b(${decimalDigits})((${frac})[fFdD]?\\\\b|\\\\.([fFdD]\\\\b)?)` },\n    { begin: `(${frac})[fFdD]?\\\\b` },\n    { begin: `\\\\b(${decimalDigits})[fFdD]\\\\b` },\n\n    // HexadecimalFloatingPointLiteral\n    { begin: `\\\\b0[xX]((${hexDigits})\\\\.?|(${hexDigits})?\\\\.(${hexDigits}))` +\n      `[pP][+-]?(${decimalDigits})[fFdD]?\\\\b` },\n\n    // DecimalIntegerLiteral\n    { begin: '\\\\b(0|[1-9](_*[0-9])*)[lL]?\\\\b' },\n\n    // HexIntegerLiteral\n    { begin: `\\\\b0[xX](${hexDigits})[lL]?\\\\b` },\n\n    // OctalIntegerLiteral\n    { begin: '\\\\b0(_*[0-7])*[lL]?\\\\b' },\n\n    // BinaryIntegerLiteral\n    { begin: '\\\\b0[bB][01](_*[01])*[lL]?\\\\b' },\n  ],\n  relevance: 0\n};\n\n/*\n Language: Kotlin\n Description: Kotlin is an OSS statically typed programming language that targets the JVM, Android, JavaScript and Native.\n Author: Sergey Mashkov \n Website: https://kotlinlang.org\n Category: common\n */\n\nfunction kotlin(hljs) {\n  const KEYWORDS = {\n    keyword:\n      'abstract as val var vararg get set class object open private protected public noinline ' +\n      'crossinline dynamic final enum if else do while for when throw try catch finally ' +\n      'import package is in fun override companion reified inline lateinit init ' +\n      'interface annotation data sealed internal infix operator out by constructor super ' +\n      'tailrec where const inner suspend typealias external expect actual',\n    built_in:\n      'Byte Short Char Int Long Boolean Float Double Void Unit Nothing',\n    literal:\n      'true false null'\n  };\n  const KEYWORDS_WITH_LABEL = {\n    className: 'keyword',\n    begin: /\\b(break|continue|return|this)\\b/,\n    starts: {\n      contains: [\n        {\n          className: 'symbol',\n          begin: /@\\w+/\n        }\n      ]\n    }\n  };\n  const LABEL = {\n    className: 'symbol',\n    begin: hljs.UNDERSCORE_IDENT_RE + '@'\n  };\n\n  // for string templates\n  const SUBST = {\n    className: 'subst',\n    begin: /\\$\\{/,\n    end: /\\}/,\n    contains: [ hljs.C_NUMBER_MODE ]\n  };\n  const VARIABLE = {\n    className: 'variable',\n    begin: '\\\\$' + hljs.UNDERSCORE_IDENT_RE\n  };\n  const STRING = {\n    className: 'string',\n    variants: [\n      {\n        begin: '\"\"\"',\n        end: '\"\"\"(?=[^\"])',\n        contains: [\n          VARIABLE,\n          SUBST\n        ]\n      },\n      // Can't use built-in modes easily, as we want to use STRING in the meta\n      // context as 'meta-string' and there's no syntax to remove explicitly set\n      // classNames in built-in modes.\n      {\n        begin: '\\'',\n        end: '\\'',\n        illegal: /\\n/,\n        contains: [ hljs.BACKSLASH_ESCAPE ]\n      },\n      {\n        begin: '\"',\n        end: '\"',\n        illegal: /\\n/,\n        contains: [\n          hljs.BACKSLASH_ESCAPE,\n          VARIABLE,\n          SUBST\n        ]\n      }\n    ]\n  };\n  SUBST.contains.push(STRING);\n\n  const ANNOTATION_USE_SITE = {\n    className: 'meta',\n    begin: '@(?:file|property|field|get|set|receiver|param|setparam|delegate)\\\\s*:(?:\\\\s*' + hljs.UNDERSCORE_IDENT_RE + ')?'\n  };\n  const ANNOTATION = {\n    className: 'meta',\n    begin: '@' + hljs.UNDERSCORE_IDENT_RE,\n    contains: [\n      {\n        begin: /\\(/,\n        end: /\\)/,\n        contains: [\n          hljs.inherit(STRING, {\n            className: 'meta-string'\n          })\n        ]\n      }\n    ]\n  };\n\n  // https://kotlinlang.org/docs/reference/whatsnew11.html#underscores-in-numeric-literals\n  // According to the doc above, the number mode of kotlin is the same as java 8,\n  // so the code below is copied from java.js\n  const KOTLIN_NUMBER_MODE = NUMERIC;\n  const KOTLIN_NESTED_COMMENT = hljs.COMMENT(\n    '/\\\\*', '\\\\*/',\n    {\n      contains: [ hljs.C_BLOCK_COMMENT_MODE ]\n    }\n  );\n  const KOTLIN_PAREN_TYPE = {\n    variants: [\n      {\n        className: 'type',\n        begin: hljs.UNDERSCORE_IDENT_RE\n      },\n      {\n        begin: /\\(/,\n        end: /\\)/,\n        contains: [] // defined later\n      }\n    ]\n  };\n  const KOTLIN_PAREN_TYPE2 = KOTLIN_PAREN_TYPE;\n  KOTLIN_PAREN_TYPE2.variants[1].contains = [ KOTLIN_PAREN_TYPE ];\n  KOTLIN_PAREN_TYPE.variants[1].contains = [ KOTLIN_PAREN_TYPE2 ];\n\n  return {\n    name: 'Kotlin',\n    aliases: [ 'kt', 'kts' ],\n    keywords: KEYWORDS,\n    contains: [\n      hljs.COMMENT(\n        '/\\\\*\\\\*',\n        '\\\\*/',\n        {\n          relevance: 0,\n          contains: [\n            {\n              className: 'doctag',\n              begin: '@[A-Za-z]+'\n            }\n          ]\n        }\n      ),\n      hljs.C_LINE_COMMENT_MODE,\n      KOTLIN_NESTED_COMMENT,\n      KEYWORDS_WITH_LABEL,\n      LABEL,\n      ANNOTATION_USE_SITE,\n      ANNOTATION,\n      {\n        className: 'function',\n        beginKeywords: 'fun',\n        end: '[(]|$',\n        returnBegin: true,\n        excludeEnd: true,\n        keywords: KEYWORDS,\n        relevance: 5,\n        contains: [\n          {\n            begin: hljs.UNDERSCORE_IDENT_RE + '\\\\s*\\\\(',\n            returnBegin: true,\n            relevance: 0,\n            contains: [ hljs.UNDERSCORE_TITLE_MODE ]\n          },\n          {\n            className: 'type',\n            begin: //,\n            keywords: 'reified',\n            relevance: 0\n          },\n          {\n            className: 'params',\n            begin: /\\(/,\n            end: /\\)/,\n            endsParent: true,\n            keywords: KEYWORDS,\n            relevance: 0,\n            contains: [\n              {\n                begin: /:/,\n                end: /[=,\\/]/,\n                endsWithParent: true,\n                contains: [\n                  KOTLIN_PAREN_TYPE,\n                  hljs.C_LINE_COMMENT_MODE,\n                  KOTLIN_NESTED_COMMENT\n                ],\n                relevance: 0\n              },\n              hljs.C_LINE_COMMENT_MODE,\n              KOTLIN_NESTED_COMMENT,\n              ANNOTATION_USE_SITE,\n              ANNOTATION,\n              STRING,\n              hljs.C_NUMBER_MODE\n            ]\n          },\n          KOTLIN_NESTED_COMMENT\n        ]\n      },\n      {\n        className: 'class',\n        beginKeywords: 'class interface trait', // remove 'trait' when removed from KEYWORDS\n        end: /[:\\{(]|$/,\n        excludeEnd: true,\n        illegal: 'extends implements',\n        contains: [\n          {\n            beginKeywords: 'public protected internal private constructor'\n          },\n          hljs.UNDERSCORE_TITLE_MODE,\n          {\n            className: 'type',\n            begin: //,\n            excludeBegin: true,\n            excludeEnd: true,\n            relevance: 0\n          },\n          {\n            className: 'type',\n            begin: /[,:]\\s*/,\n            end: /[<\\(,]|$/,\n            excludeBegin: true,\n            returnEnd: true\n          },\n          ANNOTATION_USE_SITE,\n          ANNOTATION\n        ]\n      },\n      STRING,\n      {\n        className: 'meta',\n        begin: \"^#!/usr/bin/env\",\n        end: '$',\n        illegal: '\\n'\n      },\n      KOTLIN_NUMBER_MODE\n    ]\n  };\n}\n\nmodule.exports = kotlin;\n","/**\n * @param {string} value\n * @returns {RegExp}\n * */\n\n/**\n * @param {RegExp | string } re\n * @returns {string}\n */\nfunction source(re) {\n  if (!re) return null;\n  if (typeof re === \"string\") return re;\n\n  return re.source;\n}\n\n/**\n * @param {...(RegExp | string) } args\n * @returns {string}\n */\nfunction concat(...args) {\n  const joined = args.map((x) => source(x)).join(\"\");\n  return joined;\n}\n\n/*\nLanguage: Markdown\nRequires: xml.js\nAuthor: John Crepezzi \nWebsite: https://daringfireball.net/projects/markdown/\nCategory: common, markup\n*/\n\nfunction markdown(hljs) {\n  const INLINE_HTML = {\n    begin: /<\\/?[A-Za-z_]/,\n    end: '>',\n    subLanguage: 'xml',\n    relevance: 0\n  };\n  const HORIZONTAL_RULE = {\n    begin: '^[-\\\\*]{3,}',\n    end: '$'\n  };\n  const CODE = {\n    className: 'code',\n    variants: [\n      // TODO: fix to allow these to work with sublanguage also\n      {\n        begin: '(`{3,})[^`](.|\\\\n)*?\\\\1`*[ ]*'\n      },\n      {\n        begin: '(~{3,})[^~](.|\\\\n)*?\\\\1~*[ ]*'\n      },\n      // needed to allow markdown as a sublanguage to work\n      {\n        begin: '```',\n        end: '```+[ ]*$'\n      },\n      {\n        begin: '~~~',\n        end: '~~~+[ ]*$'\n      },\n      {\n        begin: '`.+?`'\n      },\n      {\n        begin: '(?=^( {4}|\\\\t))',\n        // use contains to gobble up multiple lines to allow the block to be whatever size\n        // but only have a single open/close tag vs one per line\n        contains: [\n          {\n            begin: '^( {4}|\\\\t)',\n            end: '(\\\\n)$'\n          }\n        ],\n        relevance: 0\n      }\n    ]\n  };\n  const LIST = {\n    className: 'bullet',\n    begin: '^[ \\t]*([*+-]|(\\\\d+\\\\.))(?=\\\\s+)',\n    end: '\\\\s+',\n    excludeEnd: true\n  };\n  const LINK_REFERENCE = {\n    begin: /^\\[[^\\n]+\\]:/,\n    returnBegin: true,\n    contains: [\n      {\n        className: 'symbol',\n        begin: /\\[/,\n        end: /\\]/,\n        excludeBegin: true,\n        excludeEnd: true\n      },\n      {\n        className: 'link',\n        begin: /:\\s*/,\n        end: /$/,\n        excludeBegin: true\n      }\n    ]\n  };\n  const URL_SCHEME = /[A-Za-z][A-Za-z0-9+.-]*/;\n  const LINK = {\n    variants: [\n      // too much like nested array access in so many languages\n      // to have any real relevance\n      {\n        begin: /\\[.+?\\]\\[.*?\\]/,\n        relevance: 0\n      },\n      // popular internet URLs\n      {\n        begin: /\\[.+?\\]\\(((data|javascript|mailto):|(?:http|ftp)s?:\\/\\/).*?\\)/,\n        relevance: 2\n      },\n      {\n        begin: concat(/\\[.+?\\]\\(/, URL_SCHEME, /:\\/\\/.*?\\)/),\n        relevance: 2\n      },\n      // relative urls\n      {\n        begin: /\\[.+?\\]\\([./?&#].*?\\)/,\n        relevance: 1\n      },\n      // whatever else, lower relevance (might not be a link at all)\n      {\n        begin: /\\[.+?\\]\\(.*?\\)/,\n        relevance: 0\n      }\n    ],\n    returnBegin: true,\n    contains: [\n      {\n        className: 'string',\n        relevance: 0,\n        begin: '\\\\[',\n        end: '\\\\]',\n        excludeBegin: true,\n        returnEnd: true\n      },\n      {\n        className: 'link',\n        relevance: 0,\n        begin: '\\\\]\\\\(',\n        end: '\\\\)',\n        excludeBegin: true,\n        excludeEnd: true\n      },\n      {\n        className: 'symbol',\n        relevance: 0,\n        begin: '\\\\]\\\\[',\n        end: '\\\\]',\n        excludeBegin: true,\n        excludeEnd: true\n      }\n    ]\n  };\n  const BOLD = {\n    className: 'strong',\n    contains: [], // defined later\n    variants: [\n      {\n        begin: /_{2}/,\n        end: /_{2}/\n      },\n      {\n        begin: /\\*{2}/,\n        end: /\\*{2}/\n      }\n    ]\n  };\n  const ITALIC = {\n    className: 'emphasis',\n    contains: [], // defined later\n    variants: [\n      {\n        begin: /\\*(?!\\*)/,\n        end: /\\*/\n      },\n      {\n        begin: /_(?!_)/,\n        end: /_/,\n        relevance: 0\n      }\n    ]\n  };\n  BOLD.contains.push(ITALIC);\n  ITALIC.contains.push(BOLD);\n\n  let CONTAINABLE = [\n    INLINE_HTML,\n    LINK\n  ];\n\n  BOLD.contains = BOLD.contains.concat(CONTAINABLE);\n  ITALIC.contains = ITALIC.contains.concat(CONTAINABLE);\n\n  CONTAINABLE = CONTAINABLE.concat(BOLD, ITALIC);\n\n  const HEADER = {\n    className: 'section',\n    variants: [\n      {\n        begin: '^#{1,6}',\n        end: '$',\n        contains: CONTAINABLE\n      },\n      {\n        begin: '(?=^.+?\\\\n[=-]{2,}$)',\n        contains: [\n          {\n            begin: '^[=-]*$'\n          },\n          {\n            begin: '^',\n            end: \"\\\\n\",\n            contains: CONTAINABLE\n          }\n        ]\n      }\n    ]\n  };\n\n  const BLOCKQUOTE = {\n    className: 'quote',\n    begin: '^>\\\\s+',\n    contains: CONTAINABLE,\n    end: '$'\n  };\n\n  return {\n    name: 'Markdown',\n    aliases: [\n      'md',\n      'mkdown',\n      'mkd'\n    ],\n    contains: [\n      HEADER,\n      INLINE_HTML,\n      LIST,\n      BOLD,\n      ITALIC,\n      BLOCKQUOTE,\n      CODE,\n      HORIZONTAL_RULE,\n      LINK,\n      LINK_REFERENCE\n    ]\n  };\n}\n\nmodule.exports = markdown;\n","/*\nLanguage: Nix\nAuthor: Domen Kožar \nDescription: Nix functional language\nWebsite: http://nixos.org/nix\n*/\n\nfunction nix(hljs) {\n  const NIX_KEYWORDS = {\n    keyword:\n      'rec with let in inherit assert if else then',\n    literal:\n      'true false or and null',\n    built_in:\n      'import abort baseNameOf dirOf isNull builtins map removeAttrs throw ' +\n      'toString derivation'\n  };\n  const ANTIQUOTE = {\n    className: 'subst',\n    begin: /\\$\\{/,\n    end: /\\}/,\n    keywords: NIX_KEYWORDS\n  };\n  const ATTRS = {\n    begin: /[a-zA-Z0-9-_]+(\\s*=)/,\n    returnBegin: true,\n    relevance: 0,\n    contains: [\n      {\n        className: 'attr',\n        begin: /\\S+/\n      }\n    ]\n  };\n  const STRING = {\n    className: 'string',\n    contains: [ ANTIQUOTE ],\n    variants: [\n      {\n        begin: \"''\",\n        end: \"''\"\n      },\n      {\n        begin: '\"',\n        end: '\"'\n      }\n    ]\n  };\n  const EXPRESSIONS = [\n    hljs.NUMBER_MODE,\n    hljs.HASH_COMMENT_MODE,\n    hljs.C_BLOCK_COMMENT_MODE,\n    STRING,\n    ATTRS\n  ];\n  ANTIQUOTE.contains = EXPRESSIONS;\n  return {\n    name: 'Nix',\n    aliases: [ \"nixos\" ],\n    keywords: NIX_KEYWORDS,\n    contains: EXPRESSIONS\n  };\n}\n\nmodule.exports = nix;\n","/*\nLanguage: PowerShell\nDescription: PowerShell is a task-based command-line shell and scripting language built on .NET.\nAuthor: David Mohundro \nContributors: Nicholas Blumhardt , Victor Zhou , Nicolas Le Gall \nWebsite: https://docs.microsoft.com/en-us/powershell/\n*/\n\nfunction powershell(hljs) {\n  const TYPES = [\n    \"string\",\n    \"char\",\n    \"byte\",\n    \"int\",\n    \"long\",\n    \"bool\",\n    \"decimal\",\n    \"single\",\n    \"double\",\n    \"DateTime\",\n    \"xml\",\n    \"array\",\n    \"hashtable\",\n    \"void\"\n  ];\n\n  // https://docs.microsoft.com/en-us/powershell/scripting/developer/cmdlet/approved-verbs-for-windows-powershell-commands\n  const VALID_VERBS =\n    'Add|Clear|Close|Copy|Enter|Exit|Find|Format|Get|Hide|Join|Lock|' +\n    'Move|New|Open|Optimize|Pop|Push|Redo|Remove|Rename|Reset|Resize|' +\n    'Search|Select|Set|Show|Skip|Split|Step|Switch|Undo|Unlock|' +\n    'Watch|Backup|Checkpoint|Compare|Compress|Convert|ConvertFrom|' +\n    'ConvertTo|Dismount|Edit|Expand|Export|Group|Import|Initialize|' +\n    'Limit|Merge|Mount|Out|Publish|Restore|Save|Sync|Unpublish|Update|' +\n    'Approve|Assert|Build|Complete|Confirm|Deny|Deploy|Disable|Enable|Install|Invoke|' +\n    'Register|Request|Restart|Resume|Start|Stop|Submit|Suspend|Uninstall|' +\n    'Unregister|Wait|Debug|Measure|Ping|Repair|Resolve|Test|Trace|Connect|' +\n    'Disconnect|Read|Receive|Send|Write|Block|Grant|Protect|Revoke|Unblock|' +\n    'Unprotect|Use|ForEach|Sort|Tee|Where';\n\n  const COMPARISON_OPERATORS =\n    '-and|-as|-band|-bnot|-bor|-bxor|-casesensitive|-ccontains|-ceq|-cge|-cgt|' +\n    '-cle|-clike|-clt|-cmatch|-cne|-cnotcontains|-cnotlike|-cnotmatch|-contains|' +\n    '-creplace|-csplit|-eq|-exact|-f|-file|-ge|-gt|-icontains|-ieq|-ige|-igt|' +\n    '-ile|-ilike|-ilt|-imatch|-in|-ine|-inotcontains|-inotlike|-inotmatch|' +\n    '-ireplace|-is|-isnot|-isplit|-join|-le|-like|-lt|-match|-ne|-not|' +\n    '-notcontains|-notin|-notlike|-notmatch|-or|-regex|-replace|-shl|-shr|' +\n    '-split|-wildcard|-xor';\n\n  const KEYWORDS = {\n    $pattern: /-?[A-z\\.\\-]+\\b/,\n    keyword:\n      'if else foreach return do while until elseif begin for trap data dynamicparam ' +\n      'end break throw param continue finally in switch exit filter try process catch ' +\n      'hidden static parameter',\n    // \"echo\" relevance has been set to 0 to avoid auto-detect conflicts with shell transcripts\n    built_in:\n      'ac asnp cat cd CFS chdir clc clear clhy cli clp cls clv cnsn compare copy cp ' +\n      'cpi cpp curl cvpa dbp del diff dir dnsn ebp echo|0 epal epcsv epsn erase etsn exsn fc fhx ' +\n      'fl ft fw gal gbp gc gcb gci gcm gcs gdr gerr ghy gi gin gjb gl gm gmo gp gps gpv group ' +\n      'gsn gsnp gsv gtz gu gv gwmi h history icm iex ihy ii ipal ipcsv ipmo ipsn irm ise iwmi ' +\n      'iwr kill lp ls man md measure mi mount move mp mv nal ndr ni nmo npssc nsn nv ogv oh ' +\n      'popd ps pushd pwd r rbp rcjb rcsn rd rdr ren ri rjb rm rmdir rmo rni rnp rp rsn rsnp ' +\n      'rujb rv rvpa rwmi sajb sal saps sasv sbp sc scb select set shcm si sl sleep sls sort sp ' +\n      'spjb spps spsv start stz sujb sv swmi tee trcm type wget where wjb write'\n    // TODO: 'validate[A-Z]+' can't work in keywords\n  };\n\n  const TITLE_NAME_RE = /\\w[\\w\\d]*((-)[\\w\\d]+)*/;\n\n  const BACKTICK_ESCAPE = {\n    begin: '`[\\\\s\\\\S]',\n    relevance: 0\n  };\n\n  const VAR = {\n    className: 'variable',\n    variants: [\n      {\n        begin: /\\$\\B/\n      },\n      {\n        className: 'keyword',\n        begin: /\\$this/\n      },\n      {\n        begin: /\\$[\\w\\d][\\w\\d_:]*/\n      }\n    ]\n  };\n\n  const LITERAL = {\n    className: 'literal',\n    begin: /\\$(null|true|false)\\b/\n  };\n\n  const QUOTE_STRING = {\n    className: \"string\",\n    variants: [\n      {\n        begin: /\"/,\n        end: /\"/\n      },\n      {\n        begin: /@\"/,\n        end: /^\"@/\n      }\n    ],\n    contains: [\n      BACKTICK_ESCAPE,\n      VAR,\n      {\n        className: 'variable',\n        begin: /\\$[A-z]/,\n        end: /[^A-z]/\n      }\n    ]\n  };\n\n  const APOS_STRING = {\n    className: 'string',\n    variants: [\n      {\n        begin: /'/,\n        end: /'/\n      },\n      {\n        begin: /@'/,\n        end: /^'@/\n      }\n    ]\n  };\n\n  const PS_HELPTAGS = {\n    className: \"doctag\",\n    variants: [\n      /* no paramater help tags */\n      {\n        begin: /\\.(synopsis|description|example|inputs|outputs|notes|link|component|role|functionality)/\n      },\n      /* one parameter help tags */\n      {\n        begin: /\\.(parameter|forwardhelptargetname|forwardhelpcategory|remotehelprunspace|externalhelp)\\s+\\S+/\n      }\n    ]\n  };\n\n  const PS_COMMENT = hljs.inherit(\n    hljs.COMMENT(null, null),\n    {\n      variants: [\n        /* single-line comment */\n        {\n          begin: /#/,\n          end: /$/\n        },\n        /* multi-line comment */\n        {\n          begin: /<#/,\n          end: /#>/\n        }\n      ],\n      contains: [ PS_HELPTAGS ]\n    }\n  );\n\n  const CMDLETS = {\n    className: 'built_in',\n    variants: [\n      {\n        begin: '('.concat(VALID_VERBS, ')+(-)[\\\\w\\\\d]+')\n      }\n    ]\n  };\n\n  const PS_CLASS = {\n    className: 'class',\n    beginKeywords: 'class enum',\n    end: /\\s*[{]/,\n    excludeEnd: true,\n    relevance: 0,\n    contains: [ hljs.TITLE_MODE ]\n  };\n\n  const PS_FUNCTION = {\n    className: 'function',\n    begin: /function\\s+/,\n    end: /\\s*\\{|$/,\n    excludeEnd: true,\n    returnBegin: true,\n    relevance: 0,\n    contains: [\n      {\n        begin: \"function\",\n        relevance: 0,\n        className: \"keyword\"\n      },\n      {\n        className: \"title\",\n        begin: TITLE_NAME_RE,\n        relevance: 0\n      },\n      {\n        begin: /\\(/,\n        end: /\\)/,\n        className: \"params\",\n        relevance: 0,\n        contains: [ VAR ]\n      }\n      // CMDLETS\n    ]\n  };\n\n  // Using statment, plus type, plus assembly name.\n  const PS_USING = {\n    begin: /using\\s/,\n    end: /$/,\n    returnBegin: true,\n    contains: [\n      QUOTE_STRING,\n      APOS_STRING,\n      {\n        className: 'keyword',\n        begin: /(using|assembly|command|module|namespace|type)/\n      }\n    ]\n  };\n\n  // Comperison operators & function named parameters.\n  const PS_ARGUMENTS = {\n    variants: [\n      // PS literals are pretty verbose so it's a good idea to accent them a bit.\n      {\n        className: 'operator',\n        begin: '('.concat(COMPARISON_OPERATORS, ')\\\\b')\n      },\n      {\n        className: 'literal',\n        begin: /(-)[\\w\\d]+/,\n        relevance: 0\n      }\n    ]\n  };\n\n  const HASH_SIGNS = {\n    className: 'selector-tag',\n    begin: /@\\B/,\n    relevance: 0\n  };\n\n  // It's a very general rule so I'll narrow it a bit with some strict boundaries\n  // to avoid any possible false-positive collisions!\n  const PS_METHODS = {\n    className: 'function',\n    begin: /\\[.*\\]\\s*[\\w]+[ ]??\\(/,\n    end: /$/,\n    returnBegin: true,\n    relevance: 0,\n    contains: [\n      {\n        className: 'keyword',\n        begin: '('.concat(\n          KEYWORDS.keyword.toString().replace(/\\s/g, '|'\n          ), ')\\\\b'),\n        endsParent: true,\n        relevance: 0\n      },\n      hljs.inherit(hljs.TITLE_MODE, {\n        endsParent: true\n      })\n    ]\n  };\n\n  const GENTLEMANS_SET = [\n    // STATIC_MEMBER,\n    PS_METHODS,\n    PS_COMMENT,\n    BACKTICK_ESCAPE,\n    hljs.NUMBER_MODE,\n    QUOTE_STRING,\n    APOS_STRING,\n    // PS_NEW_OBJECT_TYPE,\n    CMDLETS,\n    VAR,\n    LITERAL,\n    HASH_SIGNS\n  ];\n\n  const PS_TYPE = {\n    begin: /\\[/,\n    end: /\\]/,\n    excludeBegin: true,\n    excludeEnd: true,\n    relevance: 0,\n    contains: [].concat(\n      'self',\n      GENTLEMANS_SET,\n      {\n        begin: \"(\" + TYPES.join(\"|\") + \")\",\n        className: \"built_in\",\n        relevance: 0\n      },\n      {\n        className: 'type',\n        begin: /[\\.\\w\\d]+/,\n        relevance: 0\n      }\n    )\n  };\n\n  PS_METHODS.contains.unshift(PS_TYPE);\n\n  return {\n    name: 'PowerShell',\n    aliases: [\n      \"ps\",\n      \"ps1\"\n    ],\n    case_insensitive: true,\n    keywords: KEYWORDS,\n    contains: GENTLEMANS_SET.concat(\n      PS_CLASS,\n      PS_FUNCTION,\n      PS_USING,\n      PS_ARGUMENTS,\n      PS_TYPE\n    )\n  };\n}\n\nmodule.exports = powershell;\n","/*\nLanguage: .properties\nContributors: Valentin Aitken , Egor Rogov \nWebsite: https://en.wikipedia.org/wiki/.properties\nCategory: common, config\n*/\n\nfunction properties(hljs) {\n\n  // whitespaces: space, tab, formfeed\n  var WS0 = '[ \\\\t\\\\f]*';\n  var WS1 = '[ \\\\t\\\\f]+';\n  // delimiter\n  var EQUAL_DELIM = WS0+'[:=]'+WS0;\n  var WS_DELIM = WS1;\n  var DELIM = '(' + EQUAL_DELIM + '|' + WS_DELIM + ')';\n  var KEY_ALPHANUM = '([^\\\\\\\\\\\\W:= \\\\t\\\\f\\\\n]|\\\\\\\\.)+';\n  var KEY_OTHER = '([^\\\\\\\\:= \\\\t\\\\f\\\\n]|\\\\\\\\.)+';\n\n  var DELIM_AND_VALUE = {\n          // skip DELIM\n          end: DELIM,\n          relevance: 0,\n          starts: {\n            // value: everything until end of line (again, taking into account backslashes)\n            className: 'string',\n            end: /$/,\n            relevance: 0,\n            contains: [\n              { begin: '\\\\\\\\\\\\\\\\'},\n              { begin: '\\\\\\\\\\\\n' }\n            ]\n          }\n        };\n\n  return {\n    name: '.properties',\n    case_insensitive: true,\n    illegal: /\\S/,\n    contains: [\n      hljs.COMMENT('^\\\\s*[!#]', '$'),\n      // key: everything until whitespace or = or : (taking into account backslashes)\n      // case of a \"normal\" key\n      {\n        returnBegin: true,\n        variants: [\n          { begin: KEY_ALPHANUM + EQUAL_DELIM, relevance: 1 },\n          { begin: KEY_ALPHANUM + WS_DELIM, relevance: 0 }\n        ],\n        contains: [\n          {\n            className: 'attr',\n            begin: KEY_ALPHANUM,\n            endsParent: true,\n            relevance: 0\n          }\n        ],\n        starts: DELIM_AND_VALUE\n      },\n      // case of key containing non-alphanumeric chars => relevance = 0\n      {\n        begin: KEY_OTHER + DELIM,\n        returnBegin: true,\n        relevance: 0,\n        contains: [\n          {\n            className: 'meta',\n            begin: KEY_OTHER,\n            endsParent: true,\n            relevance: 0\n          }\n        ],\n        starts: DELIM_AND_VALUE\n      },\n      // case of an empty key\n      {\n        className: 'attr',\n        relevance: 0,\n        begin: KEY_OTHER + WS0 + '$'\n      }\n    ]\n  };\n}\n\nmodule.exports = properties;\n","/**\n * @param {string} value\n * @returns {RegExp}\n * */\n\n/**\n * @param {RegExp | string } re\n * @returns {string}\n */\nfunction source(re) {\n  if (!re) return null;\n  if (typeof re === \"string\") return re;\n\n  return re.source;\n}\n\n/**\n * @param {RegExp | string } re\n * @returns {string}\n */\nfunction lookahead(re) {\n  return concat('(?=', re, ')');\n}\n\n/**\n * @param {...(RegExp | string) } args\n * @returns {string}\n */\nfunction concat(...args) {\n  const joined = args.map((x) => source(x)).join(\"\");\n  return joined;\n}\n\n/*\nLanguage: Ruby\nDescription: Ruby is a dynamic, open source programming language with a focus on simplicity and productivity.\nWebsite: https://www.ruby-lang.org/\nAuthor: Anton Kovalyov \nContributors: Peter Leonov , Vasily Polovnyov , Loren Segal , Pascal Hurni , Cedric Sohrauer \nCategory: common\n*/\n\nfunction ruby(hljs) {\n  const RUBY_METHOD_RE = '([a-zA-Z_]\\\\w*[!?=]?|[-+~]@|<<|>>|=~|===?|<=>|[<>]=?|\\\\*\\\\*|[-/+%^&*~`|]|\\\\[\\\\]=?)';\n  const RUBY_KEYWORDS = {\n    keyword:\n      'and then defined module in return redo if BEGIN retry end for self when ' +\n      'next until do begin unless END rescue else break undef not super class case ' +\n      'require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor ' +\n      '__FILE__',\n    built_in: 'proc lambda',\n    literal:\n      'true false nil'\n  };\n  const YARDOCTAG = {\n    className: 'doctag',\n    begin: '@[A-Za-z]+'\n  };\n  const IRB_OBJECT = {\n    begin: '#<',\n    end: '>'\n  };\n  const COMMENT_MODES = [\n    hljs.COMMENT(\n      '#',\n      '$',\n      {\n        contains: [ YARDOCTAG ]\n      }\n    ),\n    hljs.COMMENT(\n      '^=begin',\n      '^=end',\n      {\n        contains: [ YARDOCTAG ],\n        relevance: 10\n      }\n    ),\n    hljs.COMMENT('^__END__', '\\\\n$')\n  ];\n  const SUBST = {\n    className: 'subst',\n    begin: /#\\{/,\n    end: /\\}/,\n    keywords: RUBY_KEYWORDS\n  };\n  const STRING = {\n    className: 'string',\n    contains: [\n      hljs.BACKSLASH_ESCAPE,\n      SUBST\n    ],\n    variants: [\n      {\n        begin: /'/,\n        end: /'/\n      },\n      {\n        begin: /\"/,\n        end: /\"/\n      },\n      {\n        begin: /`/,\n        end: /`/\n      },\n      {\n        begin: /%[qQwWx]?\\(/,\n        end: /\\)/\n      },\n      {\n        begin: /%[qQwWx]?\\[/,\n        end: /\\]/\n      },\n      {\n        begin: /%[qQwWx]?\\{/,\n        end: /\\}/\n      },\n      {\n        begin: /%[qQwWx]?/\n      },\n      {\n        begin: /%[qQwWx]?\\//,\n        end: /\\//\n      },\n      {\n        begin: /%[qQwWx]?%/,\n        end: /%/\n      },\n      {\n        begin: /%[qQwWx]?-/,\n        end: /-/\n      },\n      {\n        begin: /%[qQwWx]?\\|/,\n        end: /\\|/\n      },\n      // in the following expressions, \\B in the beginning suppresses recognition of ?-sequences\n      // where ? is the last character of a preceding identifier, as in: `func?4`\n      {\n        begin: /\\B\\?(\\\\\\d{1,3})/\n      },\n      {\n        begin: /\\B\\?(\\\\x[A-Fa-f0-9]{1,2})/\n      },\n      {\n        begin: /\\B\\?(\\\\u\\{?[A-Fa-f0-9]{1,6}\\}?)/\n      },\n      {\n        begin: /\\B\\?(\\\\M-\\\\C-|\\\\M-\\\\c|\\\\c\\\\M-|\\\\M-|\\\\C-\\\\M-)[\\x20-\\x7e]/\n      },\n      {\n        begin: /\\B\\?\\\\(c|C-)[\\x20-\\x7e]/\n      },\n      {\n        begin: /\\B\\?\\\\?\\S/\n      },\n      { // heredocs\n        begin: /<<[-~]?'?(\\w+)\\n(?:[^\\n]*\\n)*?\\s*\\1\\b/,\n        returnBegin: true,\n        contains: [\n          {\n            begin: /<<[-~]?'?/\n          },\n          hljs.END_SAME_AS_BEGIN({\n            begin: /(\\w+)/,\n            end: /(\\w+)/,\n            contains: [\n              hljs.BACKSLASH_ESCAPE,\n              SUBST\n            ]\n          })\n        ]\n      }\n    ]\n  };\n\n  // Ruby syntax is underdocumented, but this grammar seems to be accurate\n  // as of version 2.7.2 (confirmed with (irb and `Ripper.sexp(...)`)\n  // https://docs.ruby-lang.org/en/2.7.0/doc/syntax/literals_rdoc.html#label-Numbers\n  const decimal = '[1-9](_?[0-9])*|0';\n  const digits = '[0-9](_?[0-9])*';\n  const NUMBER = {\n    className: 'number',\n    relevance: 0,\n    variants: [\n      // decimal integer/float, optionally exponential or rational, optionally imaginary\n      {\n        begin: `\\\\b(${decimal})(\\\\.(${digits}))?([eE][+-]?(${digits})|r)?i?\\\\b`\n      },\n\n      // explicit decimal/binary/octal/hexadecimal integer,\n      // optionally rational and/or imaginary\n      {\n        begin: \"\\\\b0[dD][0-9](_?[0-9])*r?i?\\\\b\"\n      },\n      {\n        begin: \"\\\\b0[bB][0-1](_?[0-1])*r?i?\\\\b\"\n      },\n      {\n        begin: \"\\\\b0[oO][0-7](_?[0-7])*r?i?\\\\b\"\n      },\n      {\n        begin: \"\\\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*r?i?\\\\b\"\n      },\n\n      // 0-prefixed implicit octal integer, optionally rational and/or imaginary\n      {\n        begin: \"\\\\b0(_?[0-7])+r?i?\\\\b\"\n      }\n    ]\n  };\n\n  const PARAMS = {\n    className: 'params',\n    begin: '\\\\(',\n    end: '\\\\)',\n    endsParent: true,\n    keywords: RUBY_KEYWORDS\n  };\n\n  const RUBY_DEFAULT_CONTAINS = [\n    STRING,\n    {\n      className: 'class',\n      beginKeywords: 'class module',\n      end: '$|;',\n      illegal: /=/,\n      contains: [\n        hljs.inherit(hljs.TITLE_MODE, {\n          begin: '[A-Za-z_]\\\\w*(::\\\\w+)*(\\\\?|!)?'\n        }),\n        {\n          begin: '<\\\\s*',\n          contains: [\n            {\n              begin: '(' + hljs.IDENT_RE + '::)?' + hljs.IDENT_RE,\n              // we already get points for <, we don't need poitns\n              // for the name also\n              relevance: 0\n            }\n          ]\n        }\n      ].concat(COMMENT_MODES)\n    },\n    {\n      className: 'function',\n      // def method_name(\n      // def method_name;\n      // def method_name (end of line)\n      begin: concat(/def\\s+/, lookahead(RUBY_METHOD_RE + \"\\\\s*(\\\\(|;|$)\")),\n      relevance: 0, // relevance comes from kewords\n      keywords: \"def\",\n      end: '$|;',\n      contains: [\n        hljs.inherit(hljs.TITLE_MODE, {\n          begin: RUBY_METHOD_RE\n        }),\n        PARAMS\n      ].concat(COMMENT_MODES)\n    },\n    {\n      // swallow namespace qualifiers before symbols\n      begin: hljs.IDENT_RE + '::'\n    },\n    {\n      className: 'symbol',\n      begin: hljs.UNDERSCORE_IDENT_RE + '(!|\\\\?)?:',\n      relevance: 0\n    },\n    {\n      className: 'symbol',\n      begin: ':(?!\\\\s)',\n      contains: [\n        STRING,\n        {\n          begin: RUBY_METHOD_RE\n        }\n      ],\n      relevance: 0\n    },\n    NUMBER,\n    {\n      // negative-look forward attemps to prevent false matches like:\n      // @ident@ or $ident$ that might indicate this is not ruby at all\n      className: \"variable\",\n      begin: '(\\\\$\\\\W)|((\\\\$|@@?)(\\\\w+))(?=[^@$?])' + `(?![A-Za-z])(?![@$?'])`\n    },\n    {\n      className: 'params',\n      begin: /\\|/,\n      end: /\\|/,\n      relevance: 0, // this could be a lot of things (in other languages) other than params\n      keywords: RUBY_KEYWORDS\n    },\n    { // regexp container\n      begin: '(' + hljs.RE_STARTERS_RE + '|unless)\\\\s*',\n      keywords: 'unless',\n      contains: [\n        {\n          className: 'regexp',\n          contains: [\n            hljs.BACKSLASH_ESCAPE,\n            SUBST\n          ],\n          illegal: /\\n/,\n          variants: [\n            {\n              begin: '/',\n              end: '/[a-z]*'\n            },\n            {\n              begin: /%r\\{/,\n              end: /\\}[a-z]*/\n            },\n            {\n              begin: '%r\\\\(',\n              end: '\\\\)[a-z]*'\n            },\n            {\n              begin: '%r!',\n              end: '![a-z]*'\n            },\n            {\n              begin: '%r\\\\[',\n              end: '\\\\][a-z]*'\n            }\n          ]\n        }\n      ].concat(IRB_OBJECT, COMMENT_MODES),\n      relevance: 0\n    }\n  ].concat(IRB_OBJECT, COMMENT_MODES);\n\n  SUBST.contains = RUBY_DEFAULT_CONTAINS;\n  PARAMS.contains = RUBY_DEFAULT_CONTAINS;\n\n  // >>\n  // ?>\n  const SIMPLE_PROMPT = \"[>?]>\";\n  // irb(main):001:0>\n  const DEFAULT_PROMPT = \"[\\\\w#]+\\\\(\\\\w+\\\\):\\\\d+:\\\\d+>\";\n  const RVM_PROMPT = \"(\\\\w+-)?\\\\d+\\\\.\\\\d+\\\\.\\\\d+(p\\\\d+)?[^\\\\d][^>]+>\";\n\n  const IRB_DEFAULT = [\n    {\n      begin: /^\\s*=>/,\n      starts: {\n        end: '$',\n        contains: RUBY_DEFAULT_CONTAINS\n      }\n    },\n    {\n      className: 'meta',\n      begin: '^(' + SIMPLE_PROMPT + \"|\" + DEFAULT_PROMPT + '|' + RVM_PROMPT + ')(?=[ ])',\n      starts: {\n        end: '$',\n        contains: RUBY_DEFAULT_CONTAINS\n      }\n    }\n  ];\n\n  COMMENT_MODES.unshift(IRB_OBJECT);\n\n  return {\n    name: 'Ruby',\n    aliases: [\n      'rb',\n      'gemspec',\n      'podspec',\n      'thor',\n      'irb'\n    ],\n    keywords: RUBY_KEYWORDS,\n    illegal: /\\/\\*/,\n    contains: [\n      hljs.SHEBANG({\n        binary: \"ruby\"\n      })\n    ]\n      .concat(IRB_DEFAULT)\n      .concat(COMMENT_MODES)\n      .concat(RUBY_DEFAULT_CONTAINS)\n  };\n}\n\nmodule.exports = ruby;\n","/*\nLanguage: Scala\nCategory: functional\nAuthor: Jan Berkel \nContributors: Erik Osheim \nWebsite: https://www.scala-lang.org\n*/\n\nfunction scala(hljs) {\n  const ANNOTATION = {\n    className: 'meta',\n    begin: '@[A-Za-z]+'\n  };\n\n  // used in strings for escaping/interpolation/substitution\n  const SUBST = {\n    className: 'subst',\n    variants: [\n      {\n        begin: '\\\\$[A-Za-z0-9_]+'\n      },\n      {\n        begin: /\\$\\{/,\n        end: /\\}/\n      }\n    ]\n  };\n\n  const STRING = {\n    className: 'string',\n    variants: [\n      {\n        begin: '\"\"\"',\n        end: '\"\"\"'\n      },\n      {\n        begin: '\"',\n        end: '\"',\n        illegal: '\\\\n',\n        contains: [ hljs.BACKSLASH_ESCAPE ]\n      },\n      {\n        begin: '[a-z]+\"',\n        end: '\"',\n        illegal: '\\\\n',\n        contains: [\n          hljs.BACKSLASH_ESCAPE,\n          SUBST\n        ]\n      },\n      {\n        className: 'string',\n        begin: '[a-z]+\"\"\"',\n        end: '\"\"\"',\n        contains: [ SUBST ],\n        relevance: 10\n      }\n    ]\n\n  };\n\n  const SYMBOL = {\n    className: 'symbol',\n    begin: '\\'\\\\w[\\\\w\\\\d_]*(?!\\')'\n  };\n\n  const TYPE = {\n    className: 'type',\n    begin: '\\\\b[A-Z][A-Za-z0-9_]*',\n    relevance: 0\n  };\n\n  const NAME = {\n    className: 'title',\n    begin: /[^0-9\\n\\t \"'(),.`{}\\[\\]:;][^\\n\\t \"'(),.`{}\\[\\]:;]+|[^0-9\\n\\t \"'(),.`{}\\[\\]:;=]/,\n    relevance: 0\n  };\n\n  const CLASS = {\n    className: 'class',\n    beginKeywords: 'class object trait type',\n    end: /[:={\\[\\n;]/,\n    excludeEnd: true,\n    contains: [\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      {\n        beginKeywords: 'extends with',\n        relevance: 10\n      },\n      {\n        begin: /\\[/,\n        end: /\\]/,\n        excludeBegin: true,\n        excludeEnd: true,\n        relevance: 0,\n        contains: [ TYPE ]\n      },\n      {\n        className: 'params',\n        begin: /\\(/,\n        end: /\\)/,\n        excludeBegin: true,\n        excludeEnd: true,\n        relevance: 0,\n        contains: [ TYPE ]\n      },\n      NAME\n    ]\n  };\n\n  const METHOD = {\n    className: 'function',\n    beginKeywords: 'def',\n    end: /[:={\\[(\\n;]/,\n    excludeEnd: true,\n    contains: [ NAME ]\n  };\n\n  return {\n    name: 'Scala',\n    keywords: {\n      literal: 'true false null',\n      keyword: 'type yield lazy override def with val var sealed abstract private trait object if forSome for while throw finally protected extends import final return else break new catch super class case package default try this match continue throws implicit'\n    },\n    contains: [\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      STRING,\n      SYMBOL,\n      TYPE,\n      METHOD,\n      CLASS,\n      hljs.C_NUMBER_MODE,\n      ANNOTATION\n    ]\n  };\n}\n\nmodule.exports = scala;\n","/*\nLanguage: Shell Session\nRequires: bash.js\nAuthor: TSUYUSATO Kitsune \nCategory: common\nAudit: 2020\n*/\n\n/** @type LanguageFn */\nfunction shell(hljs) {\n  return {\n    name: 'Shell Session',\n    aliases: [ 'console' ],\n    contains: [\n      {\n        className: 'meta',\n        // We cannot add \\s (spaces) in the regular expression otherwise it will be too broad and produce unexpected result.\n        // For instance, in the following example, it would match \"echo /path/to/home >\" as a prompt:\n        // echo /path/to/home > t.exe\n        begin: /^\\s{0,3}[/~\\w\\d[\\]()@-]*[>%$#]/,\n        starts: {\n          end: /[^\\\\](?=\\s*$)/,\n          subLanguage: 'bash'\n        }\n      }\n    ]\n  };\n}\n\nmodule.exports = shell;\n","/**\n * @param {string} value\n * @returns {RegExp}\n * */\n\n/**\n * @param {RegExp | string } re\n * @returns {string}\n */\nfunction source(re) {\n  if (!re) return null;\n  if (typeof re === \"string\") return re;\n\n  return re.source;\n}\n\n/**\n * @param {...(RegExp | string) } args\n * @returns {string}\n */\nfunction concat(...args) {\n  const joined = args.map((x) => source(x)).join(\"\");\n  return joined;\n}\n\n/**\n * Any of the passed expresssions may match\n *\n * Creates a huge this | this | that | that match\n * @param {(RegExp | string)[] } args\n * @returns {string}\n */\nfunction either(...args) {\n  const joined = '(' + args.map((x) => source(x)).join(\"|\") + \")\";\n  return joined;\n}\n\n/*\n Language: SQL\n Website: https://en.wikipedia.org/wiki/SQL\n Category: common, database\n */\n\nfunction sql(hljs) {\n  const COMMENT_MODE = hljs.COMMENT('--', '$');\n  const STRING = {\n    className: 'string',\n    variants: [\n      {\n        begin: /'/,\n        end: /'/,\n        contains: [\n          {begin: /''/ }\n        ]\n      }\n    ]\n  };\n  const QUOTED_IDENTIFIER = {\n    begin: /\"/,\n    end: /\"/,\n    contains: [ { begin: /\"\"/ } ]\n  };\n\n  const LITERALS = [\n    \"true\",\n    \"false\",\n    // Not sure it's correct to call NULL literal, and clauses like IS [NOT] NULL look strange that way.\n    // \"null\",\n    \"unknown\"\n  ];\n\n  const MULTI_WORD_TYPES = [\n    \"double precision\",\n    \"large object\",\n    \"with timezone\",\n    \"without timezone\"\n  ];\n\n  const TYPES = [\n    'bigint',\n    'binary',\n    'blob',\n    'boolean',\n    'char',\n    'character',\n    'clob',\n    'date',\n    'dec',\n    'decfloat',\n    'decimal',\n    'float',\n    'int',\n    'integer',\n    'interval',\n    'nchar',\n    'nclob',\n    'national',\n    'numeric',\n    'real',\n    'row',\n    'smallint',\n    'time',\n    'timestamp',\n    'varchar',\n    'varying', // modifier (character varying)\n    'varbinary'\n  ];\n\n  const NON_RESERVED_WORDS = [\n    \"add\",\n    \"asc\",\n    \"collation\",\n    \"desc\",\n    \"final\",\n    \"first\",\n    \"last\",\n    \"view\"\n  ];\n\n  // https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#reserved-word\n  const RESERVED_WORDS = [\n    \"abs\",\n    \"acos\",\n    \"all\",\n    \"allocate\",\n    \"alter\",\n    \"and\",\n    \"any\",\n    \"are\",\n    \"array\",\n    \"array_agg\",\n    \"array_max_cardinality\",\n    \"as\",\n    \"asensitive\",\n    \"asin\",\n    \"asymmetric\",\n    \"at\",\n    \"atan\",\n    \"atomic\",\n    \"authorization\",\n    \"avg\",\n    \"begin\",\n    \"begin_frame\",\n    \"begin_partition\",\n    \"between\",\n    \"bigint\",\n    \"binary\",\n    \"blob\",\n    \"boolean\",\n    \"both\",\n    \"by\",\n    \"call\",\n    \"called\",\n    \"cardinality\",\n    \"cascaded\",\n    \"case\",\n    \"cast\",\n    \"ceil\",\n    \"ceiling\",\n    \"char\",\n    \"char_length\",\n    \"character\",\n    \"character_length\",\n    \"check\",\n    \"classifier\",\n    \"clob\",\n    \"close\",\n    \"coalesce\",\n    \"collate\",\n    \"collect\",\n    \"column\",\n    \"commit\",\n    \"condition\",\n    \"connect\",\n    \"constraint\",\n    \"contains\",\n    \"convert\",\n    \"copy\",\n    \"corr\",\n    \"corresponding\",\n    \"cos\",\n    \"cosh\",\n    \"count\",\n    \"covar_pop\",\n    \"covar_samp\",\n    \"create\",\n    \"cross\",\n    \"cube\",\n    \"cume_dist\",\n    \"current\",\n    \"current_catalog\",\n    \"current_date\",\n    \"current_default_transform_group\",\n    \"current_path\",\n    \"current_role\",\n    \"current_row\",\n    \"current_schema\",\n    \"current_time\",\n    \"current_timestamp\",\n    \"current_path\",\n    \"current_role\",\n    \"current_transform_group_for_type\",\n    \"current_user\",\n    \"cursor\",\n    \"cycle\",\n    \"date\",\n    \"day\",\n    \"deallocate\",\n    \"dec\",\n    \"decimal\",\n    \"decfloat\",\n    \"declare\",\n    \"default\",\n    \"define\",\n    \"delete\",\n    \"dense_rank\",\n    \"deref\",\n    \"describe\",\n    \"deterministic\",\n    \"disconnect\",\n    \"distinct\",\n    \"double\",\n    \"drop\",\n    \"dynamic\",\n    \"each\",\n    \"element\",\n    \"else\",\n    \"empty\",\n    \"end\",\n    \"end_frame\",\n    \"end_partition\",\n    \"end-exec\",\n    \"equals\",\n    \"escape\",\n    \"every\",\n    \"except\",\n    \"exec\",\n    \"execute\",\n    \"exists\",\n    \"exp\",\n    \"external\",\n    \"extract\",\n    \"false\",\n    \"fetch\",\n    \"filter\",\n    \"first_value\",\n    \"float\",\n    \"floor\",\n    \"for\",\n    \"foreign\",\n    \"frame_row\",\n    \"free\",\n    \"from\",\n    \"full\",\n    \"function\",\n    \"fusion\",\n    \"get\",\n    \"global\",\n    \"grant\",\n    \"group\",\n    \"grouping\",\n    \"groups\",\n    \"having\",\n    \"hold\",\n    \"hour\",\n    \"identity\",\n    \"in\",\n    \"indicator\",\n    \"initial\",\n    \"inner\",\n    \"inout\",\n    \"insensitive\",\n    \"insert\",\n    \"int\",\n    \"integer\",\n    \"intersect\",\n    \"intersection\",\n    \"interval\",\n    \"into\",\n    \"is\",\n    \"join\",\n    \"json_array\",\n    \"json_arrayagg\",\n    \"json_exists\",\n    \"json_object\",\n    \"json_objectagg\",\n    \"json_query\",\n    \"json_table\",\n    \"json_table_primitive\",\n    \"json_value\",\n    \"lag\",\n    \"language\",\n    \"large\",\n    \"last_value\",\n    \"lateral\",\n    \"lead\",\n    \"leading\",\n    \"left\",\n    \"like\",\n    \"like_regex\",\n    \"listagg\",\n    \"ln\",\n    \"local\",\n    \"localtime\",\n    \"localtimestamp\",\n    \"log\",\n    \"log10\",\n    \"lower\",\n    \"match\",\n    \"match_number\",\n    \"match_recognize\",\n    \"matches\",\n    \"max\",\n    \"member\",\n    \"merge\",\n    \"method\",\n    \"min\",\n    \"minute\",\n    \"mod\",\n    \"modifies\",\n    \"module\",\n    \"month\",\n    \"multiset\",\n    \"national\",\n    \"natural\",\n    \"nchar\",\n    \"nclob\",\n    \"new\",\n    \"no\",\n    \"none\",\n    \"normalize\",\n    \"not\",\n    \"nth_value\",\n    \"ntile\",\n    \"null\",\n    \"nullif\",\n    \"numeric\",\n    \"octet_length\",\n    \"occurrences_regex\",\n    \"of\",\n    \"offset\",\n    \"old\",\n    \"omit\",\n    \"on\",\n    \"one\",\n    \"only\",\n    \"open\",\n    \"or\",\n    \"order\",\n    \"out\",\n    \"outer\",\n    \"over\",\n    \"overlaps\",\n    \"overlay\",\n    \"parameter\",\n    \"partition\",\n    \"pattern\",\n    \"per\",\n    \"percent\",\n    \"percent_rank\",\n    \"percentile_cont\",\n    \"percentile_disc\",\n    \"period\",\n    \"portion\",\n    \"position\",\n    \"position_regex\",\n    \"power\",\n    \"precedes\",\n    \"precision\",\n    \"prepare\",\n    \"primary\",\n    \"procedure\",\n    \"ptf\",\n    \"range\",\n    \"rank\",\n    \"reads\",\n    \"real\",\n    \"recursive\",\n    \"ref\",\n    \"references\",\n    \"referencing\",\n    \"regr_avgx\",\n    \"regr_avgy\",\n    \"regr_count\",\n    \"regr_intercept\",\n    \"regr_r2\",\n    \"regr_slope\",\n    \"regr_sxx\",\n    \"regr_sxy\",\n    \"regr_syy\",\n    \"release\",\n    \"result\",\n    \"return\",\n    \"returns\",\n    \"revoke\",\n    \"right\",\n    \"rollback\",\n    \"rollup\",\n    \"row\",\n    \"row_number\",\n    \"rows\",\n    \"running\",\n    \"savepoint\",\n    \"scope\",\n    \"scroll\",\n    \"search\",\n    \"second\",\n    \"seek\",\n    \"select\",\n    \"sensitive\",\n    \"session_user\",\n    \"set\",\n    \"show\",\n    \"similar\",\n    \"sin\",\n    \"sinh\",\n    \"skip\",\n    \"smallint\",\n    \"some\",\n    \"specific\",\n    \"specifictype\",\n    \"sql\",\n    \"sqlexception\",\n    \"sqlstate\",\n    \"sqlwarning\",\n    \"sqrt\",\n    \"start\",\n    \"static\",\n    \"stddev_pop\",\n    \"stddev_samp\",\n    \"submultiset\",\n    \"subset\",\n    \"substring\",\n    \"substring_regex\",\n    \"succeeds\",\n    \"sum\",\n    \"symmetric\",\n    \"system\",\n    \"system_time\",\n    \"system_user\",\n    \"table\",\n    \"tablesample\",\n    \"tan\",\n    \"tanh\",\n    \"then\",\n    \"time\",\n    \"timestamp\",\n    \"timezone_hour\",\n    \"timezone_minute\",\n    \"to\",\n    \"trailing\",\n    \"translate\",\n    \"translate_regex\",\n    \"translation\",\n    \"treat\",\n    \"trigger\",\n    \"trim\",\n    \"trim_array\",\n    \"true\",\n    \"truncate\",\n    \"uescape\",\n    \"union\",\n    \"unique\",\n    \"unknown\",\n    \"unnest\",\n    \"update   \",\n    \"upper\",\n    \"user\",\n    \"using\",\n    \"value\",\n    \"values\",\n    \"value_of\",\n    \"var_pop\",\n    \"var_samp\",\n    \"varbinary\",\n    \"varchar\",\n    \"varying\",\n    \"versioning\",\n    \"when\",\n    \"whenever\",\n    \"where\",\n    \"width_bucket\",\n    \"window\",\n    \"with\",\n    \"within\",\n    \"without\",\n    \"year\",\n  ];\n\n  // these are reserved words we have identified to be functions\n  // and should only be highlighted in a dispatch-like context\n  // ie, array_agg(...), etc.\n  const RESERVED_FUNCTIONS = [\n    \"abs\",\n    \"acos\",\n    \"array_agg\",\n    \"asin\",\n    \"atan\",\n    \"avg\",\n    \"cast\",\n    \"ceil\",\n    \"ceiling\",\n    \"coalesce\",\n    \"corr\",\n    \"cos\",\n    \"cosh\",\n    \"count\",\n    \"covar_pop\",\n    \"covar_samp\",\n    \"cume_dist\",\n    \"dense_rank\",\n    \"deref\",\n    \"element\",\n    \"exp\",\n    \"extract\",\n    \"first_value\",\n    \"floor\",\n    \"json_array\",\n    \"json_arrayagg\",\n    \"json_exists\",\n    \"json_object\",\n    \"json_objectagg\",\n    \"json_query\",\n    \"json_table\",\n    \"json_table_primitive\",\n    \"json_value\",\n    \"lag\",\n    \"last_value\",\n    \"lead\",\n    \"listagg\",\n    \"ln\",\n    \"log\",\n    \"log10\",\n    \"lower\",\n    \"max\",\n    \"min\",\n    \"mod\",\n    \"nth_value\",\n    \"ntile\",\n    \"nullif\",\n    \"percent_rank\",\n    \"percentile_cont\",\n    \"percentile_disc\",\n    \"position\",\n    \"position_regex\",\n    \"power\",\n    \"rank\",\n    \"regr_avgx\",\n    \"regr_avgy\",\n    \"regr_count\",\n    \"regr_intercept\",\n    \"regr_r2\",\n    \"regr_slope\",\n    \"regr_sxx\",\n    \"regr_sxy\",\n    \"regr_syy\",\n    \"row_number\",\n    \"sin\",\n    \"sinh\",\n    \"sqrt\",\n    \"stddev_pop\",\n    \"stddev_samp\",\n    \"substring\",\n    \"substring_regex\",\n    \"sum\",\n    \"tan\",\n    \"tanh\",\n    \"translate\",\n    \"translate_regex\",\n    \"treat\",\n    \"trim\",\n    \"trim_array\",\n    \"unnest\",\n    \"upper\",\n    \"value_of\",\n    \"var_pop\",\n    \"var_samp\",\n    \"width_bucket\",\n  ];\n\n  // these functions can\n  const POSSIBLE_WITHOUT_PARENS = [\n    \"current_catalog\",\n    \"current_date\",\n    \"current_default_transform_group\",\n    \"current_path\",\n    \"current_role\",\n    \"current_schema\",\n    \"current_transform_group_for_type\",\n    \"current_user\",\n    \"session_user\",\n    \"system_time\",\n    \"system_user\",\n    \"current_time\",\n    \"localtime\",\n    \"current_timestamp\",\n    \"localtimestamp\"\n  ];\n\n  // those exist to boost relevance making these very\n  // \"SQL like\" keyword combos worth +1 extra relevance\n  const COMBOS = [\n    \"create table\",\n    \"insert into\",\n    \"primary key\",\n    \"foreign key\",\n    \"not null\",\n    \"alter table\",\n    \"add constraint\",\n    \"grouping sets\",\n    \"on overflow\",\n    \"character set\",\n    \"respect nulls\",\n    \"ignore nulls\",\n    \"nulls first\",\n    \"nulls last\",\n    \"depth first\",\n    \"breadth first\"\n  ];\n\n  const FUNCTIONS = RESERVED_FUNCTIONS;\n\n  const KEYWORDS = [...RESERVED_WORDS, ...NON_RESERVED_WORDS].filter((keyword) => {\n    return !RESERVED_FUNCTIONS.includes(keyword);\n  });\n\n  const VARIABLE = {\n    className: \"variable\",\n    begin: /@[a-z0-9]+/,\n  };\n\n  const OPERATOR = {\n    className: \"operator\",\n    begin: /[-+*/=%^~]|&&?|\\|\\|?|!=?|<(?:=>?|<|>)?|>[>=]?/,\n    relevance: 0,\n  };\n\n  const FUNCTION_CALL = {\n    begin: concat(/\\b/, either(...FUNCTIONS), /\\s*\\(/),\n    keywords: {\n      built_in: FUNCTIONS\n    }\n  };\n\n  // keywords with less than 3 letters are reduced in relevancy\n  function reduceRelevancy(list, {exceptions, when} = {}) {\n    const qualifyFn = when;\n    exceptions = exceptions || [];\n    return list.map((item) => {\n      if (item.match(/\\|\\d+$/) || exceptions.includes(item)) {\n        return item;\n      } else if (qualifyFn(item)) {\n        return `${item}|0`;\n      } else {\n        return item;\n      }\n    });\n  }\n\n  return {\n    name: 'SQL',\n    case_insensitive: true,\n    // does not include {} or HTML tags ` x.length < 3 }),\n      literal: LITERALS,\n      type: TYPES,\n      built_in: POSSIBLE_WITHOUT_PARENS\n    },\n    contains: [\n      {\n        begin: either(...COMBOS),\n        keywords: {\n          $pattern: /[\\w\\.]+/,\n          keyword: KEYWORDS.concat(COMBOS),\n          literal: LITERALS,\n          type: TYPES\n        },\n      },\n      {\n        className: \"type\",\n        begin: either(...MULTI_WORD_TYPES)\n      },\n      FUNCTION_CALL,\n      VARIABLE,\n      STRING,\n      QUOTED_IDENTIFIER,\n      hljs.C_NUMBER_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      COMMENT_MODE,\n      OPERATOR\n    ]\n  };\n}\n\nmodule.exports = sql;\n","/**\n * @param {string} value\n * @returns {RegExp}\n * */\n\n/**\n * @param {RegExp | string } re\n * @returns {string}\n */\nfunction source(re) {\n  if (!re) return null;\n  if (typeof re === \"string\") return re;\n\n  return re.source;\n}\n\n/**\n * @param {RegExp | string } re\n * @returns {string}\n */\nfunction lookahead(re) {\n  return concat('(?=', re, ')');\n}\n\n/**\n * @param {RegExp | string } re\n * @returns {string}\n */\nfunction optional(re) {\n  return concat('(', re, ')?');\n}\n\n/**\n * @param {...(RegExp | string) } args\n * @returns {string}\n */\nfunction concat(...args) {\n  const joined = args.map((x) => source(x)).join(\"\");\n  return joined;\n}\n\n/**\n * Any of the passed expresssions may match\n *\n * Creates a huge this | this | that | that match\n * @param {(RegExp | string)[] } args\n * @returns {string}\n */\nfunction either(...args) {\n  const joined = '(' + args.map((x) => source(x)).join(\"|\") + \")\";\n  return joined;\n}\n\n/*\nLanguage: HTML, XML\nWebsite: https://www.w3.org/XML/\nCategory: common\nAudit: 2020\n*/\n\n/** @type LanguageFn */\nfunction xml(hljs) {\n  // Element names can contain letters, digits, hyphens, underscores, and periods\n  const TAG_NAME_RE = concat(/[A-Z_]/, optional(/[A-Z0-9_.-]*:/), /[A-Z0-9_.-]*/);\n  const XML_IDENT_RE = /[A-Za-z0-9._:-]+/;\n  const XML_ENTITIES = {\n    className: 'symbol',\n    begin: /&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/\n  };\n  const XML_META_KEYWORDS = {\n    begin: /\\s/,\n    contains: [\n      {\n        className: 'meta-keyword',\n        begin: /#?[a-z_][a-z1-9_-]+/,\n        illegal: /\\n/\n      }\n    ]\n  };\n  const XML_META_PAR_KEYWORDS = hljs.inherit(XML_META_KEYWORDS, {\n    begin: /\\(/,\n    end: /\\)/\n  });\n  const APOS_META_STRING_MODE = hljs.inherit(hljs.APOS_STRING_MODE, {\n    className: 'meta-string'\n  });\n  const QUOTE_META_STRING_MODE = hljs.inherit(hljs.QUOTE_STRING_MODE, {\n    className: 'meta-string'\n  });\n  const TAG_INTERNALS = {\n    endsWithParent: true,\n    illegal: /`]+/\n              }\n            ]\n          }\n        ]\n      }\n    ]\n  };\n  return {\n    name: 'HTML, XML',\n    aliases: [\n      'html',\n      'xhtml',\n      'rss',\n      'atom',\n      'xjb',\n      'xsd',\n      'xsl',\n      'plist',\n      'wsf',\n      'svg'\n    ],\n    case_insensitive: true,\n    contains: [\n      {\n        className: 'meta',\n        begin: //,\n        relevance: 10,\n        contains: [\n          XML_META_KEYWORDS,\n          QUOTE_META_STRING_MODE,\n          APOS_META_STRING_MODE,\n          XML_META_PAR_KEYWORDS,\n          {\n            begin: /\\[/,\n            end: /\\]/,\n            contains: [\n              {\n                className: 'meta',\n                begin: //,\n                contains: [\n                  XML_META_KEYWORDS,\n                  XML_META_PAR_KEYWORDS,\n                  QUOTE_META_STRING_MODE,\n                  APOS_META_STRING_MODE\n                ]\n              }\n            ]\n          }\n        ]\n      },\n      hljs.COMMENT(\n        //,\n        {\n          relevance: 10\n        }\n      ),\n      {\n        begin: //,\n        relevance: 10\n      },\n      XML_ENTITIES,\n      {\n        className: 'meta',\n        begin: /<\\?xml/,\n        end: /\\?>/,\n        relevance: 10\n      },\n      {\n        className: 'tag',\n        /*\n        The lookahead pattern (?=...) ensures that 'begin' only matches\n        ')/,\n        end: />/,\n        keywords: {\n          name: 'style'\n        },\n        contains: [ TAG_INTERNALS ],\n        starts: {\n          end: /<\\/style>/,\n          returnEnd: true,\n          subLanguage: [\n            'css',\n            'xml'\n          ]\n        }\n      },\n      {\n        className: 'tag',\n        // See the comment in the 
      +
      +
      +
      +
      \ No newline at end of file
      diff --git a/src/docs/asciidoc/faq.adoc b/src/docs/asciidoc/faq.adoc
      index d967882..a28a82b 100644
      --- a/src/docs/asciidoc/faq.adoc
      +++ b/src/docs/asciidoc/faq.adoc
      @@ -110,7 +110,7 @@ springdoc.swagger-ui.tagsSorter=alpha
       * You have to set the following property:
       [source,properties]
       ----
      -springdoc.swagger-ui.supportedSubmitMethods="get", "put", "post", "delete", "options", "head", "patch", "trace"
      +springdoc.swagger-ui.supportedSubmitMethods=get, put, post, delete, options, head, patch, trace
       ----
       
       === How can I add  Reusable Enums ?
      @@ -143,7 +143,7 @@ springdoc.packagesToScan=package1, package2
       
       These can be set by creating a `swaggerUiConfig` bean as follows:
       [source,kotlin]
      ----
      +----
       @Bean
       @Primary
       fun swaggerUiConfig(config: SwaggerUiConfigProperties): SwaggerUiConfigProperties {
      @@ -151,7 +151,7 @@ fun swaggerUiConfig(config: SwaggerUiConfigProperties): SwaggerUiConfigPropertie
           config.queryConfigEnabled = true
           return config
       }
      ----
      +----
       
       === How can I ignore some field of model ?
       * You can use the following annotation on the top of the field that you want to hide:
      @@ -264,7 +264,7 @@ RequestHeader set X-Forwarded-Prefix "/custom-path"
       server.use-forward-headers=true
       ----
       * If this is not enough, Spring Framework provides a `ForwardedHeaderFilter`. You can register it as a Servlet Filter in your application by setting server.forward-headers-strategy is set to FRAMEWORK.
      -* Since Spring Boot 3.2, this is the new property to handle reverse proxy headers:
      +* Since Spring Boot 2.2, this is the new property to handle reverse proxy headers:
       
       [source,properties]
       ----
      @@ -281,6 +281,28 @@ ForwardedHeaderFilter forwardedHeaderFilter() {
       }
       ----
       
      +* If you need to manually adjust the URL displayed in the Swagger UI, implement the `ServerBaseUrlCustomizer` interface. This might be necessary to remove the port number, for example.
      +
      +[source,java]
      +----
      +@Bean
      +public class CustomServerBaseUrlCustomizer implements ServerBaseUrlCustomizer {
      +    @Override
      +    public String customize(String serverBaseUrl) {
      +        try {
      +            URL url = new URL(serverBaseUrl);
      +            if (url.getHost().contains(".com")) {
      +                serverBaseUrl = new URL(url.getProtocol(),url.getHost(),url.getFile()).toString();
      +            }
      +        } catch (MalformedURLException ex) {
      +            // nothing we can do
      +        }
      +
      +        return serverBaseUrl;
      +    }
      +}
      +----
      +
       ===  Is `@JsonView` annotations in Spring MVC APIs supported?
       * Yes
       
      @@ -294,12 +316,12 @@ springdoc.swagger-ui.path= /swagger-ui/api-docs.html
       
       === How can I test the Swagger UI?
       * You can have a look on this sample test of the UI:
      -** link:https://github.com/springdoc/springdoc-openapi/blob/master/springdoc-openapi-starter-webmvc-ui/src/test/java/test/org/springdoc/ui/app1/SpringDocApp1Test.java[https://github.com/springdoc/springdoc-openapi/blob/master/springdoc-openapi-starter-webmvc-ui/src/test/java/test/org/springdoc/ui/app1/SpringDocApp1Test.java, window="_blank"]
      +** link:https://github.com/springdoc/springdoc-openapi/blob/main/springdoc-openapi-starter-webmvc-ui/src/test/java/test/org/springdoc/ui/app1/SpringDocApp1Test.java[https://github.com/springdoc/springdoc-openapi/blob/main/springdoc-openapi-starter-webmvc-ui/src/test/java/test/org/springdoc/ui/app1/SpringDocApp1Test.java, window="_blank"]
       
       === How can I customise the OpenAPI object ?
       * You can write your own implementation of `OpenApiCustomizer`.
       * An example is available on:
      -** link:https://github.com/springdoc/springdoc-openapi/blob/master/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/app39/SpringDocApp39Test.java[https://github.com/springdoc/springdoc-openapi/blob/master/springdoc-openapi-webflux-core/src/test/java/test/org/springdoc/api/app39/SpringDocTestApp.java, window="_blank"]
      +** link:https://github.com/springdoc/springdoc-openapi/blob/main/springdoc-openapi-starter-webflux-api/src/test/java/test/org/springdoc/api/app39/SpringDocTestApp.java[https://github.com/springdoc/springdoc-openapi/blob/main/springdoc-openapi-starter-webflux-api/src/test/java/test/org/springdoc/api/app39/SpringDocTestApp.java, window="_blank"]
       
       [source,java]
       ----
      @@ -572,6 +594,35 @@ public OpenApiCustomizer customerGlobalHeaderOpenApiCustomizer() {
       
       === Is file upload supported ?
       * The library supports the main file types: `MultipartFile`,  `@RequestPart`, `FilePart`
      +* You can upload a file as follows:
      +
      +[source,java]
      +----
      +import io.swagger.v3.oas.annotations.Parameter;
      +import io.swagger.v3.oas.annotations.media.Content;
      +import io.swagger.v3.oas.annotations.media.Encoding;
      +import io.swagger.v3.oas.annotations.parameters.RequestBody;
      +
      +@PostMapping(value = "/upload", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
      +public ResponseEntity upload(@Parameter(description = "file") final MultipartFile file) {
      +    return null;
      +}
      +
      +@PostMapping(value = "/uploadFileWithQuery", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
      +public ResponseEntity uploadFileWithQuery(@Parameter(description = "file") @RequestPart("file") final MultipartFile file,
      +        @Parameter(description = "An extra query parameter") @RequestParam String name) {
      +    return null;
      +}
      +
      +@PostMapping(value = "/uploadFileWithJson", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}, produces = {
      +        MediaType.APPLICATION_JSON_VALUE})
      +public ResponseEntity uploadFileWithJson(
      +        @RequestBody(content = @Content(encoding = @Encoding(name = "jsonRequest", contentType = MediaType.APPLICATION_JSON_VALUE)))
      +        @Parameter(description = "An extra JSON payload sent with file") @RequestPart("jsonRequest") final JsonRequest jsonRequest,
      +        @RequestPart("file") final MultipartFile file) {
      +    return null;
      +}
      +----
       
       === Can I use `@Parameter` inside `@Operation` annotation?
       * Yes, it's supported
      @@ -608,11 +659,6 @@ SpringDocConfigProperties springDocConfigProperties() {
       ObjectMapperProvider objectMapperProvider(SpringDocConfigProperties springDocConfigProperties){
           return new ObjectMapperProvider(springDocConfigProperties);
       }
      -
      -@Bean
      -SpringDocUIConfiguration SpringDocUIConfiguration(Optional optionalSwaggerUiConfigProperties){
      -    return new SpringDocUIConfiguration(optionalSwaggerUiConfigProperties);
      -}
       ----
       
       * Then configure, the path of your custom UI yaml file.
      @@ -662,18 +708,23 @@ springdoc.group-configs[0].packages-to-scan=test.org.springdoc.api
       
       === How can I use the last `springdoc-openapi` SNAPSHOT ?
       * For testing purposes only, you can test temporarily using the last `springdoc-openapi` SNAPSHOT
      -* To achieve that, you can on your pom.xml or your settings.xml the following section:
      +* To achieve that, configure your pom.xml file with the following `` section:
       
       [source,xml]
       ----
      -     
      -       
      -         snapshots-repo
      -         https://s01.oss.sonatype.org/content/repositories/snapshots
      -         false
      -         true
      -       
      -     
      +    
      +      
      +        Central Portal Snapshots
      +        central-portal-snapshots
      +        https://central.sonatype.com/repository/maven-snapshots/
      +        
      +          false
      +        
      +        
      +          true
      +        
      +      
      +    
       ----
       
       === How can I use enable `springdoc-openapi` MonetaryAmount support ?
      @@ -715,7 +766,7 @@ If the CSRF Token is required, swagger-ui automatically sends the new XSRF-TOKEN
       
       If your XSRF-TOKEN isn't standards-based, you can use a requestInterceptor to manually capture and attach the latest xsrf token to requests programmatically via spring resource transformer:
       
      -* link:https://github.com/swagger-api/swagger-ui/blob/master/docs/usage/configuration.md#requestinterceptor[https://github.com/swagger-api/swagger-ui/blob/master/docs/usage/configuration.md#requestinterceptor, window="_blank"]
      +* link:https://github.com/swagger-api/swagger-ui/blob/master/docs/usage/configuration.md#requestinterceptor[https://github.com/swagger-api/swagger-ui/blob/main/docs/usage/configuration.md#requestinterceptor, window="_blank"]
       
       Starting from release v1.4.4 of springdoc-openapi, a new property is added to enable CSRF support, while using standard header names:
       [source,properties]
      @@ -944,6 +995,77 @@ public class OpenAPIConfig {
       }
       ----
       
      +=== How to Integrate Open API 3 with Spring project (not Spring Boot)?
      +When your application is using spring without (spring-boot), you need to add beans and  auto-configuration that are natively provided in spring-boot.
      +
      +For example, lets assume you want load the swagger-ui in spring-mvc application:
      +
      +* You mainly, need to add the springdoc-openapi module
      +
      +[source,xml]
      +----
      +
      +   org.springdoc
      +   springdoc-openapi-starter-webmvc-ui
      +   last.version
      +
      +----
      +
      +* If you don't have the spring-boot and spring-boot-autoconfigure dependencies, you need to add them. And pay attention to the compatibility matrix, between you spring.version and spring-boot.version. For example, in this case (spring.version=5.1.12.RELEASE):
      +
      +[source,xml]
      +----
      +		
      +			org.springframework.boot
      +			spring-boot-autoconfigure
      +			3.3.3
      +		
      +----
      +
      +* Scan for the `springdoc-openapi` 'auto-configuration classes that spring-boot automatically loads for you.
      +* Depending on your module, you can find them on the file: `spring.factories` of each `springdoc-openapi` module.
      +
      +[source,java]
      +----
      +@Configuration
      +@EnableWebMvc
      +public class WebConfig implements WebApplicationInitializer {
      +
      +	@Override
      +	public void onStartup(ServletContext servletContext)  {
      +		WebApplicationContext context = getContext();
      +		servletContext.addListener(new ContextLoaderListener(context));
      +		ServletRegistration.Dynamic dispatcher = servletContext.addServlet("RestServlet",
      +				new DispatcherServlet(context));
      +		dispatcher.setLoadOnStartup(1);
      +		dispatcher.addMapping("/*");
      +	}
      +
      +	private AnnotationConfigWebApplicationContext getContext() {
      +		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
      +		context.register(this.getClass(),
      +				SpringDocConfiguration.class,
      +				SpringDocConfigProperties.class,
      +				SpringDocSpecPropertiesConfiguration.class,
      +				SpringDocWebMvcConfiguration.class, 
      +				MultipleOpenApiSupportConfiguration.class,
      +				SwaggerConfig.class,
      +				SwaggerUiConfigProperties.class,
      +				SwaggerUiOAuthProperties.class,
      +		);
      +		return context;
      +	}
      +}
      +----
      +
      +* Depending on your module, you can find them on the file: `org.springframework.boot.autoconfigure.AutoConfiguration.imports` of each `springdoc-openapi` module.
      +* For groups usage make sure your  `GroupedOpenApi` Beans are scanned.
      +* If additionally, you are using custom `context path`: `/my-servlet-path`. Make sure you declare the following property:
      +[source,properties]
      +----
      +spring.mvc.servlet.path=/my-servlet-path
      +----
      +
       === What is the compatibility matrix of `springdoc-openapi` with `spring-boot` ?
       `springdoc-openapi 2.x` is compatible with `spring-boot 3`.
       
      @@ -952,9 +1074,13 @@ In general, **you should only pick the last stable version as per today {springd
       More precisely, this the exhaustive list of spring-boot versions against which `springdoc-openapi` has been built:
       
       |===
      -| spring-boot Versions | Minimum springdoc-openapi Versions
      -
      -|`3.0.x` | `2.0.x`+
      +| Spring Boot Versions | Springdoc OpenAPI Versions
      +|`3.5.x` | `2.8.x` 
      +|`3.4.x` | `2.7.x` - `2.8.x`
      +|`3.3.x` | `2.6.x`
      +|`3.2.x` | `2.3.x` - `2.5.x`
      +|`3.1.x` | `2.2.x`
      +|`3.0.x` | `2.0.x` - `2.1.x`
       |`2.7.x`, `1.5.x` | `1.6.0`+
       |`2.6.x`, `1.5.x` | `1.6.0`+
       |`2.5.x`, `1.5.x` | `1.5.9`+
      @@ -993,17 +1119,3 @@ This can be fixed by adding the `-parameters` arg to the Maven Compiler Plugin.
       
       ----
       
      -++++
      -        
      -        
      -        
      -        
      -++++
      \ No newline at end of file
      diff --git a/src/docs/asciidoc/favicon.ico b/src/docs/asciidoc/favicon.ico
      index 0dfbcd7..45468e6 100644
      Binary files a/src/docs/asciidoc/favicon.ico and b/src/docs/asciidoc/favicon.ico differ
      diff --git a/src/docs/asciidoc/features.adoc b/src/docs/asciidoc/features.adoc
      index c832293..34e8863 100644
      --- a/src/docs/asciidoc/features.adoc
      +++ b/src/docs/asciidoc/features.adoc
      @@ -73,15 +73,15 @@ RouterFunction routes() {
       
       Here is the link for some sample codes:
       
      -- link:https://github.com/springdoc/springdoc-openapi/blob/master/springdoc-openapi-webflux-core/src/test/java/test/org/springdoc/api/app90/HelloRouter.java[HelloRouter]
      -- link:https://github.com/springdoc/springdoc-openapi/blob/master/springdoc-openapi-webflux-core/src/test/java/test/org/springdoc/api/app90/quotes/QuotesRouter.java[QuotesRouter]
      -- link:https://github.com/springdoc/springdoc-openapi/blob/master/springdoc-openapi-webflux-core/src/test/java/test/org/springdoc/api/app90/book/BookRouter.java[BookRouter]
      -- link:https://github.com/springdoc/springdoc-openapi/blob/master/springdoc-openapi-webflux-core/src/test/java/test/org/springdoc/api/app90/employee/EmployeeRouter.java[EmployeeRouter]
      -- link:https://github.com/springdoc/springdoc-openapi/blob/master/springdoc-openapi-webflux-core/src/test/java/test/org/springdoc/api/app90/position/PositionRouter.java[PositionRouter]
      +- link:https://github.com/springdoc/springdoc-openapi/blob/master/springdoc-openapi-starter-webflux-api/src/test/java/test/org/springdoc/api/app90/HelloRouter.java[HelloRouter]
      +- link:https://github.com/springdoc/springdoc-openapi/blob/master/springdoc-openapi-starter-webflux-api/src/test/java/test/org/springdoc/api/app90/quotes/QuotesRouter.java[QuotesRouter]
      +- link:https://github.com/springdoc/springdoc-openapi/blob/master/springdoc-openapi-starter-webflux-api/src/test/java/test/org/springdoc/api/app90/book/BookRouter.java[BookRouter]
      +- link:https://github.com/springdoc/springdoc-openapi/blob/master/springdoc-openapi-starter-webflux-api/src/test/java/test/org/springdoc/api/app90/employee/EmployeeRouter.java[EmployeeRouter]
      +- link:https://github.com/springdoc/springdoc-openapi/blob/master/springdoc-openapi-starter-webflux-api/src/test/java/test/org/springdoc/api/app90/position/PositionRouter.java[PositionRouter]
       
       And the Demo code, using the functional endpoints DSL:
       
      -- link:https://github.com/springdoc/springdoc-openapi-demos/tree/2.x/demo-spring-boot-3-webflux-functional[Sample webflux application using functional DSL]
      +- link:https://github.com/springdoc/springdoc-openapi-demos/tree/master/demo-spring-boot-3-webflux-functional[Sample webflux application using functional DSL]
       
       Since version `v1.3.8`, the support of functional endpoints has been added.
       Two main annotations have been added for this purpose: `@RouterOperations` and `@RouterOperation`.
      @@ -160,11 +160,11 @@ For that, `@RouterOperation` fields must help identify uniquely the concerned ro
       
       Some code samples are available on GITHUB of demos:
       
      -* link:https://github.com/springdoc/springdoc-openapi-demos/tree/master/springdoc-openapi-spring-boot-2-webflux-functional[Sample application with Functional Endpoints documentation, window="_blank"]
      +* link:https://github.com/springdoc/springdoc-openapi-demos/tree/master/demo-spring-boot-3-webflux-functional[Sample application with Functional Endpoints documentation, window="_blank"]
       
       And some project tests: (from app69 to app75)
       
      -* link:https://github.com/springdoc/springdoc-openapi/tree/master/springdoc-openapi-webflux-core/src/test/java/test/org/springdoc/api[Sample code with Functional Endpoints documentation, window="_blank"]
      +* link:https://github.com/springdoc/springdoc-openapi/tree/master/springdoc-openapi-starter-webflux-api/src/test/java/test/org/springdoc/api[Sample code with Functional Endpoints documentation, window="_blank"]
       
       === Integration with WildFly
       
      @@ -180,16 +180,15 @@ And some project tests: (from app69 to app75)
       ----
       
       ++++
      -        
      -        
      -        
      -        
      +
      +
      +
       ++++
      \ No newline at end of file
      diff --git a/src/docs/asciidoc/getting-started.adoc b/src/docs/asciidoc/getting-started.adoc
      index f82a480..8bc4a06 100644
      --- a/src/docs/asciidoc/getting-started.adoc
      +++ b/src/docs/asciidoc/getting-started.adoc
      @@ -20,7 +20,7 @@ This will automatically deploy swagger-ui to a spring-boot application:
       **  server: The server name or IP
       **  port: The server port
       **  context-path: The context path of the application
      -*   Documentation can be available in yaml format as well, on the following path : /v3/api-docs.yaml
      +*   Documentation will be available in yaml format as well, on the following path : /v3/api-docs.yaml
       
       TIP: For custom path of the swagger documentation in HTML format, add a custom springdoc property, in your spring-boot configuration file: .
       
      @@ -32,16 +32,15 @@ springdoc.swagger-ui.path=/swagger-ui.html
       ----
       
       ++++
      -        
      -        
      -        
      -        
      +
      +
      +
       ++++
      \ No newline at end of file
      diff --git a/src/docs/asciidoc/img/LVM_Versicherung_2010_logo.svg.png b/src/docs/asciidoc/img/LVM_Versicherung_2010_logo.svg.png
      new file mode 100644
      index 0000000..5aac7e9
      Binary files /dev/null and b/src/docs/asciidoc/img/LVM_Versicherung_2010_logo.svg.png differ
      diff --git a/src/docs/asciidoc/img/gdnext.png b/src/docs/asciidoc/img/gdnext.png
      new file mode 100644
      index 0000000..1523834
      Binary files /dev/null and b/src/docs/asciidoc/img/gdnext.png differ
      diff --git a/src/docs/asciidoc/img/jetbrains.svg b/src/docs/asciidoc/img/jetbrains.svg
      deleted file mode 100644
      index 75d4d21..0000000
      --- a/src/docs/asciidoc/img/jetbrains.svg
      +++ /dev/null
      @@ -1,66 +0,0 @@
      -
      -
      -
      -
      -	
      -		
      -		
      -	
      -	
      -	
      -		
      -		
      -		
      -	
      -	
      -	
      -		
      -		
      -		
      -		
      -	
      -	
      -	
      -		
      -		
      -		
      -	
      -	
      -	
      -		
      -		
      -		
      -			
      -			
      -			
      -			
      -			
      -			
      -			
      -			
      -			
      -		
      -	
      -
      -
      diff --git a/src/docs/asciidoc/img/springdoc/springdoc-favicon.svg b/src/docs/asciidoc/img/springdoc/springdoc-favicon.svg
      new file mode 100644
      index 0000000..21eeef6
      --- /dev/null
      +++ b/src/docs/asciidoc/img/springdoc/springdoc-favicon.svg
      @@ -0,0 +1,166 @@
      +
      +
      +
      +
      Created with Fabric.js 4.6.0
      
      
      
      
      		
      		
      		
      		
      		
      		
      		
      		
      		
      		
      		
      		
      		
      		
      		
      		
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      diff --git a/src/docs/asciidoc/img/springdoc/springdoc-logo.svg b/src/docs/asciidoc/img/springdoc/springdoc-logo.svg
      new file mode 100644
      index 0000000..f3f7bb8
      --- /dev/null
      +++ b/src/docs/asciidoc/img/springdoc/springdoc-logo.svg
      @@ -0,0 +1,139 @@
      +
      +
      +
      +
      Created with Fabric.js 4.6.0
      
      
      
      
      		
      		
      		
      		
      		
      		
      		
      		
      		
      		
      		
      		
      		
      		
      		
      		
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      diff --git a/src/docs/asciidoc/index.adoc b/src/docs/asciidoc/index.adoc
      index 7f26b58..332cab8 100644
      --- a/src/docs/asciidoc/index.adoc
      +++ b/src/docs/asciidoc/index.adoc
      @@ -19,9 +19,17 @@ This project is sponsored by
                 
       		   
       		  
      +          
      +		   
      +		  
      +          
      +		   
      +		  
               

      ++++ +link:https://github.com/springdoc/springdoc-openapi[View project on GitHub, window="_blank"] image:img/github-logo.png[link="https://github.com/springdoc/springdoc-openapi"] + include::intro.adoc[] include::getting-started.adoc[] diff --git a/src/docs/asciidoc/intro.adoc b/src/docs/asciidoc/intro.adoc index bab79f0..5859101 100644 --- a/src/docs/asciidoc/intro.adoc +++ b/src/docs/asciidoc/intro.adoc @@ -26,17 +26,3 @@ image::img/spring-io-24.png[spring.io conference] This is a community-based project, not maintained by the Spring Framework Contributors (Pivotal). -++++ - - - - -++++ \ No newline at end of file diff --git a/src/docs/asciidoc/migrating-from-springdoc-v1.adoc b/src/docs/asciidoc/migrating-from-springdoc-v1.adoc index 9e1d0b4..b4fd773 100644 --- a/src/docs/asciidoc/migrating-from-springdoc-v1.adoc +++ b/src/docs/asciidoc/migrating-from-springdoc-v1.adoc @@ -54,17 +54,3 @@ In addition: * Replace `springdoc-openapi-ui` by `springdoc-openapi-starter-webmvc-ui` * Replace `springdoc-openapi-webflux-ui` by `springdoc-openapi-starter-webflux-ui` -++++ - - - - -++++ diff --git a/src/docs/asciidoc/migrating-from-springfox.adoc b/src/docs/asciidoc/migrating-from-springfox.adoc index 9346af6..4d74d2e 100644 --- a/src/docs/asciidoc/migrating-from-springfox.adoc +++ b/src/docs/asciidoc/migrating-from-springfox.adoc @@ -20,7 +20,7 @@ Package for swagger 3 annotations is `io.swagger.v3.oas.annotations`. - `@ApiImplicitParam` -> `@Parameter` - `@ApiImplicitParams` -> `@Parameters` - `@ApiModel` -> `@Schema` -- `@ApiModelProperty(hidden = true)` -> `@Schema(accessMode = READ_ONLY)` +- `@ApiModelProperty(allowEmptyValue = true)` -> `@Schema(nullable = true)` - `@ApiModelProperty` -> `@Schema` - `@ApiOperation(value = "foo", notes = "bar")` -> `@Operation(summary = "foo", description = "bar")` - `@ApiParam` -> `@Parameter` @@ -110,17 +110,4 @@ springdoc.pathsToMatch=/v1, /api/balance/** ** link:index.html#how-can-i-hide-an-operation-or-a-controller-from-documentation[how-can-i-hide-an-operation-or-a-controller-from-documentation] -++++ - - - - -++++ + diff --git a/src/docs/asciidoc/modules.adoc b/src/docs/asciidoc/modules.adoc index 7bfd4f1..295a55a 100644 --- a/src/docs/asciidoc/modules.adoc +++ b/src/docs/asciidoc/modules.adoc @@ -35,7 +35,7 @@ springdoc.api-docs.path=/api-docs === Spring WebFlux support -* Documentation can be available in yaml format as well, on the following path : /v3/api-docs.yaml +* Documentation will be available in yaml format as well, on the following path : /v3/api-docs.yaml * Add the library to the list of your project dependencies (No additional configuration is needed) [source,xml, subs="attributes+"] @@ -206,7 +206,7 @@ public Function, Flux> lowercase() { Some code samples are available on GITHUB of demos: -* link:https://github.com/springdoc/springdoc-openapi-demos/tree/master/springdoc-openapi-spring-cloud-function[Sample applications with Spring Cloud Function Web, window="_blank"] +* link:https://github.com/springdoc/springdoc-openapi-demos/tree/master/demo-spring-cloud-function[Sample applications with Spring Cloud Function Web, window="_blank"] === Kotlin support @@ -288,17 +288,21 @@ Ensure that you add it as well as its annotation processor to your project's dep TIP: If both a swagger-annotation description and a javadoc comment are present. The value of the swagger-annotation description will be used. -++++ - - - - -++++ \ No newline at end of file +=== Springdoc-openapi BOM +Starting from version `v2.8.7`, `springdoc-openapi` provides a BOM (Bill of Materials) to manage the dependencies of the project. +You can declare it in your project as follows: + +[source,xml, subs="attributes+"] +---- + + + + org.springdoc + springdoc-openapi-bom + {springdoc-version} + pom + import + + + +---- \ No newline at end of file diff --git a/src/docs/asciidoc/other-resources.adoc b/src/docs/asciidoc/other-resources.adoc index b721e5c..eca3349 100644 --- a/src/docs/asciidoc/other-resources.adoc +++ b/src/docs/asciidoc/other-resources.adoc @@ -18,24 +18,10 @@ The artifacts can be viewed accessed at the following locations: Releases: -* link:https://s01.oss.sonatype.org/content/groups/public/org/springdoc/[https://s01.oss.sonatype.org/content/groups/public/org/springdoc/, window="_blank"] +* link:https://central.sonatype.com/search?q=g:org.springdoc[https://central.sonatype.com/search?q=g:org.springdoc, window="_blank"] Snapshots: -* link:https://s01.oss.sonatype.org/content/repositories/snapshots/org/springdoc/[https://s01.oss.sonatype.org/content/repositories/snapshots/org/springdoc/, window="_blank", window="_blank"] - - -++++ - - - - -++++ \ No newline at end of file +* link:https://central.sonatype.com/service/rest/repository/browse/maven-snapshots/org/springdoc/[https://central.sonatype.com/service/rest/repository/browse/maven-snapshots/org/springdoc/, window="_blank", window="_blank"] + + diff --git a/src/docs/asciidoc/plugins.adoc b/src/docs/asciidoc/plugins.adoc index 998b489..aabccf4 100644 --- a/src/docs/asciidoc/plugins.adoc +++ b/src/docs/asciidoc/plugins.adoc @@ -37,7 +37,7 @@ In order to use this functionality, you need to add the plugin declaration on th org.springdoc springdoc-openapi-maven-plugin - 1.4 + 1.5 integration-test @@ -79,17 +79,3 @@ For more custom configuration of `springdoc-openapi-gradle-plugin` ,you can cons * link:https://github.com/springdoc/springdoc-openapi-gradle-plugin[https://github.com/springdoc/springdoc-openapi-gradle-plugin, window="_blank"] -++++ - - - - -++++ \ No newline at end of file diff --git a/src/docs/asciidoc/properties.adoc b/src/docs/asciidoc/properties.adoc index 9d21278..b0948ba 100644 --- a/src/docs/asciidoc/properties.adoc +++ b/src/docs/asciidoc/properties.adoc @@ -1,7 +1,7 @@ [[properties]] == Springdoc-openapi Properties -`springdoc-openapi` relies on standard link:https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config[spring configuration properties, window="_blank"] (yml or properties) using the standard files locations. +`springdoc-openapi` relies on standard link:https://docs.spring.io/spring-boot/reference/features/external-config.html[spring configuration properties, window="_blank"] (yml or properties) using the standard files locations. === springdoc-openapi core properties diff --git a/src/docs/asciidoc/sponsor.adoc b/src/docs/asciidoc/sponsor.adoc index 34b8cd7..ed4bc53 100644 --- a/src/docs/asciidoc/sponsor.adoc +++ b/src/docs/asciidoc/sponsor.adoc @@ -19,6 +19,12 @@ Thank you to our bronze sponsors! + + + + + +

      ++++ @@ -44,17 +50,4 @@ Gold sponsors donate $500 per month to the project, and get the following benefi - If issues are not created by the end of the month, the remaining ones are lost. -++++ - - - - -++++ + diff --git a/src/docs/asciidoc/thanks.adoc b/src/docs/asciidoc/thanks.adoc index 9d47d2c..2034eaf 100644 --- a/src/docs/asciidoc/thanks.adoc +++ b/src/docs/asciidoc/thanks.adoc @@ -5,19 +5,5 @@ * Thanks a lot link:https://www.jetbrains.com/?from=springdoc-openapi[JetBrains, window="_blank"] for supporting springdoc-openapi project. -image::img/jetbrains.svg[JetBrains] +image::https://resources.jetbrains.com/storage/products/company/brand/logos/jetbrains.svg[JetBrains logo] -++++ - - - - -++++ \ No newline at end of file diff --git a/src/docs/asciidoc/ui-properties.adoc b/src/docs/asciidoc/ui-properties.adoc index c466f9b..ecce440 100644 --- a/src/docs/asciidoc/ui-properties.adoc +++ b/src/docs/asciidoc/ui-properties.adoc @@ -7,7 +7,7 @@ |springdoc.swagger-ui.enabled | `true` | `Boolean`. To disable the swagger-ui endpoint (/swagger-ui.html by default). |springdoc.swagger-ui.configUrl | `/v3/api-docs/swagger-config` | `String`. URL to fetch external configuration document from. |springdoc.swagger-ui.layout | `BaseLayout` | `String`. The name of a component available via the plugin system to use as the top-level layout for Swagger UI. -|springdoc.swagger-ui.validatorUrl | `https://validator.swagger.io/validator` | By default, Swagger UI attempts to validate specs against swagger.io's online validator. You can use this parameter to set a different validator URL, for example for locally deployed validators link:https://github.com/swagger-api/validator-badge[Validator Badge, window="_blank"]. Setting it to either `none`, `127.0.0.1` or `localhost` will disable validation. +|springdoc.swagger-ui.validatorUrl | | By default, Swagger UI does not validate specs. You can use this parameter to set a validator URL, for example for against swagger.io’s online validator. |springdoc.swagger-ui.tryItOutEnabled | `false` |`Boolean`. Controls whether the "Try it out" section should be enabled by default. |springdoc.swagger-ui.filter | `false` | `Boolean OR String`. If set, enables filtering. The top bar will show an edit box that you can use to filter the tagged operations that are shown. Can be Boolean to enable or disable, or a string, in which case filtering will be enabled using that string as the filter expression. Filtering is case sensitive matching the filter expression anywhere inside the tag. |springdoc.swagger-ui.operationsSorter | | `Function=(a => a)`. Apply a sort to the operation list of each API. It can be 'alpha' (sort by paths alphanumerically), 'method' (sort by HTTP method) or a function (see Array.prototype.sort() to know how sort function works). Default is the order returned by the server unchanged. @@ -24,7 +24,7 @@ |springdoc.swagger-ui.showExtensions | `false` | `Boolean`. Controls the display of vendor extension (`x-`) fields and values for Operations, Parameters, and Schema. |springdoc.swagger-ui.url | | `String`.To configure, the path of a custom OpenAPI file . Will be ignored if `urls` is used. |springdoc.swagger-ui.showCommonExtensions | `false` | `Boolean`. Controls the display of extensions (`pattern`, `maxLength`, `minLength`, `maximum`, `minimum`) fields and values for Parameters. -|springdoc.swagger-ui.supportedSubmitMethods | | `Array=["get", "put", "post", "delete", "options", "head", "patch", "trace"]`. List of HTTP methods that have the "Try it out" feature enabled. An empty array disables "Try it out" for all operations. This does not filter the operations from the display. +|springdoc.swagger-ui.supportedSubmitMethods | | `Array=[get, put, post, delete, options, head, patch, trace]`. List of HTTP methods that have the "Try it out" feature enabled. An empty array disables "Try it out" for all operations. This does not filter the operations from the display. |springdoc.swagger-ui.queryConfigEnabled | `false` | `Boolean`. Disabled since `v1.6.0`. This parameter enables (legacy) overriding configuration parameters via URL search params. link:https://github.com/swagger-api/swagger-ui/security/advisories/GHSA-qrmm-w75w-3wpx[See security advisory , window="_blank"] before enabling this feature. |springdoc.swagger-ui.oauth. additionalQueryStringParams | | `String`. Additional query parameters added to authorizationUrl and tokenUrl. |springdoc.swagger-ui.disable-swagger-default-url | `false` | `Boolean`. To disable the swagger-ui default petstore url. (Available since v1.4.1). @@ -51,17 +51,16 @@ |=== ++++ - - - - + + + ++++ diff --git a/src/docs/asciidoc/v1/core-properties.adoc b/src/docs/asciidoc/v1/core-properties.adoc index 6416863..19d8c0f 100644 --- a/src/docs/asciidoc/v1/core-properties.adoc +++ b/src/docs/asciidoc/v1/core-properties.adoc @@ -19,7 +19,6 @@ |springdoc.auto-tag-classes | `true` | `Boolean`. To disable the springdoc-openapi automatic tags. |springdoc.model-and-view-allowed | `false` | `Boolean`. To allow RestControllers with ModelAndView return to appear in the OpenAPI description. |springdoc.override-with-generic-response | `true` | `Boolean`. When true, automatically adds @ControllerAdvice responses to all the generated responses. -|springdoc.api-docs.groups.enabled | `true` | `Boolean`. To disable the springdoc-openapi groups. |springdoc.group-configs[0].group | | `String`.The group name |springdoc.group-configs[0].display-name | | `String`.The display name of the group. |springdoc.group-configs[0].packages-to-scan | `*`| `List of Strings`.The list of packages to scan for a group (comma separated) @@ -55,17 +54,3 @@ |springdoc.trim-kotlin-indent | `false` | `Boolean`. Adjust indentation when parsing the `@Operation` annotation in Kotlin. |=== -++++ - - - - -++++ \ No newline at end of file diff --git a/src/docs/asciidoc/v1/demos.adoc b/src/docs/asciidoc/v1/demos.adoc index 8ce0aa7..d3f69e3 100644 --- a/src/docs/asciidoc/v1/demos.adoc +++ b/src/docs/asciidoc/v1/demos.adoc @@ -16,17 +16,3 @@ image::img/pets.png[pets.png] === Source code of the Demo Applications * link:https://github.com/springdoc/springdoc-openapi-demos.git[https://github.com/springdoc/springdoc-openapi-demos.git, window="_blank"] -++++ - - - - -++++ \ No newline at end of file diff --git a/src/docs/asciidoc/v1/docinfo-footer.html b/src/docs/asciidoc/v1/docinfo-footer.html index e19f1b2..e69de29 100644 --- a/src/docs/asciidoc/v1/docinfo-footer.html +++ b/src/docs/asciidoc/v1/docinfo-footer.html @@ -1,39 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/src/docs/asciidoc/v1/faq.adoc b/src/docs/asciidoc/v1/faq.adoc index 6ccec22..04630f2 100644 --- a/src/docs/asciidoc/v1/faq.adoc +++ b/src/docs/asciidoc/v1/faq.adoc @@ -110,7 +110,7 @@ springdoc.swagger-ui.tagsSorter=alpha * You have to set the following property: [source,properties] ---- -springdoc.swagger-ui.supportedSubmitMethods="get", "put", "post", "delete", "options", "head", "patch", "trace" +springdoc.swagger-ui.supportedSubmitMethods=get, put, post, delete, options, head, patch, trace ---- === How can I add Reusable Enums? @@ -143,7 +143,7 @@ springdoc.packagesToScan=package1, package2 These can be set by creating a `swaggerUiConfig` bean as follows: [source,kotlin] ---- +---- @Bean @Primary fun swaggerUiConfig(config: SwaggerUiConfigProperties): SwaggerUiConfigProperties { @@ -151,7 +151,7 @@ fun swaggerUiConfig(config: SwaggerUiConfigProperties): SwaggerUiConfigPropertie config.queryConfigEnabled = true return config } ---- +---- === How can I ignore some field of model? * You can use the following annotation on the top of the field that you want to hide: @@ -301,14 +301,14 @@ springdoc.swagger-ui.path= /swagger-ui/api-docs.html === How can I customise the OpenAPI object? * You can write your own implementation of `OpenApiCustomizer`. * An example is available on: -** link:https://github.com/springdoc/springdoc-openapi/blob/master/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app39/SpringDocApp39Test.java[https://github.com/springdoc/springdoc-openapi/blob/master/springdoc-openapi-webflux-core/src/test/java/test/org/springdoc/api/app39/SpringDocTestApp.java, window="_blank"] +** link:https://github.com/springdoc/springdoc-openapi/blob/main/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app39/SpringDocTestApp.java[https://github.com/springdoc/springdoc-openapi/blob/main/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app39/SpringDocTestApp.java, window="_blank"] [source,java] ---- @Bean -public OpenApiCustomiser consumerTypeHeaderOpenAPICustomiser() { -return openApi -> openApi.getPaths().values().stream().flatMap(pathItem -> pathItem.readOperations().stream()) - .forEach(operation -> operation.addParametersItem(new HeaderParameter().$ref("#/components/parameters/myConsumerTypeHeader"))); +public OpenApiCustomizer customerGlobalHeaderOpenApiCustomizer() { + return openApi -> openApi.getPaths().values().stream().flatMap(pathItem -> pathItem.readOperations().stream()) + .forEach(operation -> operation.addParametersItem(new HeaderParameter().$ref("#/components/parameters/myGlobalHeader"))); } ---- @@ -606,11 +606,6 @@ SpringDocConfigProperties springDocConfigProperties() { ObjectMapperProvider objectMapperProvider(SpringDocConfigProperties springDocConfigProperties){ return new ObjectMapperProvider(springDocConfigProperties); } - -@Bean -SpringDocUIConfiguration SpringDocUIConfiguration(Optional optionalSwaggerUiConfigProperties){ - return new SpringDocUIConfiguration(optionalSwaggerUiConfigProperties); -} ---- * Then configure, the path of your custom UI yaml file. @@ -734,18 +729,23 @@ spring.mvc.servlet.path=/my-servlet-path === How can I use the last `springdoc-openapi` SNAPSHOT ? * For testing purposes only, you can test temporarily using the last `springdoc-openapi` SNAPSHOT -* To achieve that, you can on your pom.xml or your settings.xml the following section: +* To achieve that, configure your pom.xml file with the following `` section: [source,xml] ---- - - - snapshots-repo - https://s01.oss.sonatype.org/content/repositories/snapshots - false - true - - + + + Central Portal Snapshots + central-portal-snapshots + https://central.sonatype.com/repository/maven-snapshots/ + + false + + + true + + + ---- === How can I use enable `springdoc-openapi` MonetaryAmount support? @@ -1032,17 +1032,3 @@ When overriding the default spring-boot registered `HttpMessageConverter`, you s ---- NOTE: Order is very important, when registering `HttpMessageConverters`. -++++ - - - - -++++ \ No newline at end of file diff --git a/src/docs/asciidoc/v1/features.adoc b/src/docs/asciidoc/v1/features.adoc index 5e8cac7..2b12c02 100644 --- a/src/docs/asciidoc/v1/features.adoc +++ b/src/docs/asciidoc/v1/features.adoc @@ -179,17 +179,3 @@ And some project tests: (from app69 to app75) ---- -++++ - - - - -++++ \ No newline at end of file diff --git a/src/docs/asciidoc/v1/getting-started.adoc b/src/docs/asciidoc/v1/getting-started.adoc index cd196cc..b4f3015 100644 --- a/src/docs/asciidoc/v1/getting-started.adoc +++ b/src/docs/asciidoc/v1/getting-started.adoc @@ -20,7 +20,7 @@ This will automatically deploy swagger-ui to a spring-boot application: ** server: The server name or IP ** port: The server port ** context-path: The context path of the application -* Documentation can be available in yaml format as well, on the following path : /v3/api-docs.yaml +* Documentation will be available in yaml format as well, on the following path : /v3/api-docs.yaml TIP: For custom path of the swagger documentation in HTML format, add a custom springdoc property, in your spring-boot configuration file: . @@ -31,17 +31,3 @@ TIP: For custom path of the swagger documentation in HTML format, add a custom s springdoc.swagger-ui.path=/swagger-ui.html ---- -++++ - - - - -++++ \ No newline at end of file diff --git a/src/docs/asciidoc/v1/index.adoc b/src/docs/asciidoc/v1/index.adoc index 40c4954..d6c415b 100644 --- a/src/docs/asciidoc/v1/index.adoc +++ b/src/docs/asciidoc/v1/index.adoc @@ -17,6 +17,12 @@ This project is sponsored by + + + + + +

      ++++ diff --git a/src/docs/asciidoc/v1/intro.adoc b/src/docs/asciidoc/v1/intro.adoc index 55bb3a4..8a15af9 100644 --- a/src/docs/asciidoc/v1/intro.adoc +++ b/src/docs/asciidoc/v1/intro.adoc @@ -24,17 +24,3 @@ image::img/springdoc-openapi-prez.gif[spring.io conference] This is a community-based project, not maintained by the Spring Framework Contributors (Pivotal). -++++ - - - - -++++ \ No newline at end of file diff --git a/src/docs/asciidoc/v1/migrating-from-springfox.adoc b/src/docs/asciidoc/v1/migrating-from-springfox.adoc index 6e039b3..890b435 100644 --- a/src/docs/asciidoc/v1/migrating-from-springfox.adoc +++ b/src/docs/asciidoc/v1/migrating-from-springfox.adoc @@ -20,7 +20,7 @@ Package for swagger 3 annotations is `io.swagger.v3.oas.annotations`. - `@ApiImplicitParam` -> `@Parameter` - `@ApiImplicitParams` -> `@Parameters` - `@ApiModel` -> `@Schema` -- `@ApiModelProperty(hidden = true)` -> `@Schema(accessMode = READ_ONLY)` +- `@ApiModelProperty(allowEmptyValue = true)` -> `@Schema(nullable = true)` - `@ApiModelProperty` -> `@Schema` - `@ApiOperation(value = "foo", notes = "bar")` -> `@Operation(summary = "foo", description = "bar")` - `@ApiParam` -> `@Parameter` @@ -111,17 +111,4 @@ springdoc.pathsToMatch=/v1, /api/balance/** * To hide an operation or a controller from documentation ** link:index.html#how-can-i-hide-an-operation-or-a-controller-from-documentation[how-can-i-hide-an-operation-or-a-controller-from-documentation] -++++ - - - - -++++ + diff --git a/src/docs/asciidoc/v1/modules.adoc b/src/docs/asciidoc/v1/modules.adoc index 55d3555..f0f2a94 100644 --- a/src/docs/asciidoc/v1/modules.adoc +++ b/src/docs/asciidoc/v1/modules.adoc @@ -35,7 +35,7 @@ springdoc.api-docs.path=/api-docs === Spring WebFlux support -* Documentation can be available in yaml format as well, on the following path : /v3/api-docs.yaml +* Documentation will be available in yaml format as well, on the following path : /v3/api-docs.yaml * Add the library to the list of your project dependencies (No additional configuration is needed) [source,xml, subs="attributes+"] @@ -294,17 +294,3 @@ NOTE: Make sure, you enable the annotation processor of `therapi-runtime-javadoc TIP: If both a swagger-annotation description and a javadoc comment are present. The value of the swagger-annotation description will be used. -++++ - - - - -++++ \ No newline at end of file diff --git a/src/docs/asciidoc/v1/other-resources.adoc b/src/docs/asciidoc/v1/other-resources.adoc index ca22e34..2f1c64f 100644 --- a/src/docs/asciidoc/v1/other-resources.adoc +++ b/src/docs/asciidoc/v1/other-resources.adoc @@ -2,7 +2,6 @@ == Other resources === Additional resources to get started -- link:https://github.com/springdoc/springdoc-openapi[View project on GitHub, window="_blank"] image:img/github-logo.png[link="https://github.com/springdoc/springdoc-openapi"] - link:https://prezi.com/view/r4DP4TCmYUJk1eaqjKG4/[Springdoc-openapi presentation, window="_blank"] - link:https://www.baeldung.com/spring-rest-openapi-documentation[Baeldung, window="_blank"] - link:https://dzone.com/articles/openapi-3-documentation-with-spring-boot[DZone Part1, window="_blank"] @@ -18,23 +17,10 @@ The artifacts can be viewed accessed at the following locations: Releases: -* link:https://s01.oss.sonatype.org/content/groups/public/org/springdoc/[https://s01.oss.sonatype.org/content/groups/public/org/springdoc/, window="_blank"] +* link:https://central.sonatype.com/search?q=g:org.springdoc[https://central.sonatype.com/search?q=g:org.springdoc, window="_blank"] Snapshots: -* link:https://s01.oss.sonatype.org/content/repositories/snapshots/org/springdoc/[https://s01.oss.sonatype.org/content/repositories/snapshots/org/springdoc/, window="_blank", window="_blank"] - -++++ - - - - -++++ +* link:https://central.sonatype.com/service/rest/repository/browse/maven-snapshots/org/springdoc/[https://central.sonatype.com/service/rest/repository/browse/maven-snapshots/org/springdoc/, window="_blank", window="_blank"] + + diff --git a/src/docs/asciidoc/v1/plugins.adoc b/src/docs/asciidoc/v1/plugins.adoc index d14a621..6a1e7c8 100644 --- a/src/docs/asciidoc/v1/plugins.adoc +++ b/src/docs/asciidoc/v1/plugins.adoc @@ -37,7 +37,7 @@ In order to use this functionality, you need to add the plugin declaration on th org.springdoc springdoc-openapi-maven-plugin - 1.4 + 1.5 integration-test @@ -79,17 +79,3 @@ For more custom configuration of `springdoc-openapi-gradle-plugin` ,you can cons * link:https://github.com/springdoc/springdoc-openapi-gradle-plugin[https://github.com/springdoc/springdoc-openapi-gradle-plugin, window="_blank"] -++++ - - - - -++++ \ No newline at end of file diff --git a/src/docs/asciidoc/v1/privacy-policy.adoc b/src/docs/asciidoc/v1/privacy-policy.adoc index f158492..8363f6f 100644 --- a/src/docs/asciidoc/v1/privacy-policy.adoc +++ b/src/docs/asciidoc/v1/privacy-policy.adoc @@ -144,17 +144,3 @@ Response Time: We make every effort to respond to your request within one month If you have any questions or concerns about this Policy or its implementation, you may contact us at support@springdoc.org. -++++ - - - - -++++ \ No newline at end of file diff --git a/src/docs/asciidoc/v1/sponsor.adoc b/src/docs/asciidoc/v1/sponsor.adoc index 7beac85..7a55653 100644 --- a/src/docs/asciidoc/v1/sponsor.adoc +++ b/src/docs/asciidoc/v1/sponsor.adoc @@ -19,6 +19,12 @@ Thank you to our bronze sponsors! + + + + + +

      ++++ @@ -44,17 +50,3 @@ Gold sponsors donate $500 per month to the project, and get the following benefi - Company logos on all https://springdoc.org page footers - If issues are not created by the end of the month, the remaining ones are lost. -++++ - - - - -++++ \ No newline at end of file diff --git a/src/docs/asciidoc/v1/thanks.adoc b/src/docs/asciidoc/v1/thanks.adoc index 9d47d2c..2034eaf 100644 --- a/src/docs/asciidoc/v1/thanks.adoc +++ b/src/docs/asciidoc/v1/thanks.adoc @@ -5,19 +5,5 @@ * Thanks a lot link:https://www.jetbrains.com/?from=springdoc-openapi[JetBrains, window="_blank"] for supporting springdoc-openapi project. -image::img/jetbrains.svg[JetBrains] +image::https://resources.jetbrains.com/storage/products/company/brand/logos/jetbrains.svg[JetBrains logo] -++++ - - - - -++++ \ No newline at end of file diff --git a/src/docs/asciidoc/v1/ui-properties.adoc b/src/docs/asciidoc/v1/ui-properties.adoc index c466f9b..943e290 100644 --- a/src/docs/asciidoc/v1/ui-properties.adoc +++ b/src/docs/asciidoc/v1/ui-properties.adoc @@ -7,8 +7,8 @@ |springdoc.swagger-ui.enabled | `true` | `Boolean`. To disable the swagger-ui endpoint (/swagger-ui.html by default). |springdoc.swagger-ui.configUrl | `/v3/api-docs/swagger-config` | `String`. URL to fetch external configuration document from. |springdoc.swagger-ui.layout | `BaseLayout` | `String`. The name of a component available via the plugin system to use as the top-level layout for Swagger UI. -|springdoc.swagger-ui.validatorUrl | `https://validator.swagger.io/validator` | By default, Swagger UI attempts to validate specs against swagger.io's online validator. You can use this parameter to set a different validator URL, for example for locally deployed validators link:https://github.com/swagger-api/validator-badge[Validator Badge, window="_blank"]. Setting it to either `none`, `127.0.0.1` or `localhost` will disable validation. -|springdoc.swagger-ui.tryItOutEnabled | `false` |`Boolean`. Controls whether the "Try it out" section should be enabled by default. +|springdoc.swagger-ui.validatorUrl | | By default, Swagger UI does not validate specs. You can use this parameter to set a validator URL, for example for against swagger.io’s online validator. +|springdoc.swagger-ui.tryItOutEnabled | `true` |`Boolean`. Controls whether the "Try it out" section should be enabled by default. |springdoc.swagger-ui.filter | `false` | `Boolean OR String`. If set, enables filtering. The top bar will show an edit box that you can use to filter the tagged operations that are shown. Can be Boolean to enable or disable, or a string, in which case filtering will be enabled using that string as the filter expression. Filtering is case sensitive matching the filter expression anywhere inside the tag. |springdoc.swagger-ui.operationsSorter | | `Function=(a => a)`. Apply a sort to the operation list of each API. It can be 'alpha' (sort by paths alphanumerically), 'method' (sort by HTTP method) or a function (see Array.prototype.sort() to know how sort function works). Default is the order returned by the server unchanged. |springdoc.swagger-ui.tagsSorter | | `Function=(a => a)`. Apply a sort to the tag list of each API. It can be 'alpha' (sort by paths alphanumerically) or a function link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort[see Array.prototype.sort() , window="_blank"] to learn how to write a sort function). Two tag name strings are passed to the sorter for each pass. Default is the order determined by Swagger UI. @@ -24,7 +24,7 @@ |springdoc.swagger-ui.showExtensions | `false` | `Boolean`. Controls the display of vendor extension (`x-`) fields and values for Operations, Parameters, and Schema. |springdoc.swagger-ui.url | | `String`.To configure, the path of a custom OpenAPI file . Will be ignored if `urls` is used. |springdoc.swagger-ui.showCommonExtensions | `false` | `Boolean`. Controls the display of extensions (`pattern`, `maxLength`, `minLength`, `maximum`, `minimum`) fields and values for Parameters. -|springdoc.swagger-ui.supportedSubmitMethods | | `Array=["get", "put", "post", "delete", "options", "head", "patch", "trace"]`. List of HTTP methods that have the "Try it out" feature enabled. An empty array disables "Try it out" for all operations. This does not filter the operations from the display. +|springdoc.swagger-ui.supportedSubmitMethods | | `Array=[get, put, post, delete, options, head, patch, trace]`. List of HTTP methods that have the "Try it out" feature enabled. An empty array disables "Try it out" for all operations. This does not filter the operations from the display. |springdoc.swagger-ui.queryConfigEnabled | `false` | `Boolean`. Disabled since `v1.6.0`. This parameter enables (legacy) overriding configuration parameters via URL search params. link:https://github.com/swagger-api/swagger-ui/security/advisories/GHSA-qrmm-w75w-3wpx[See security advisory , window="_blank"] before enabling this feature. |springdoc.swagger-ui.oauth. additionalQueryStringParams | | `String`. Additional query parameters added to authorizationUrl and tokenUrl. |springdoc.swagger-ui.disable-swagger-default-url | `false` | `Boolean`. To disable the swagger-ui default petstore url. (Available since v1.4.1). @@ -50,18 +50,5 @@ |=== -++++ - - - - -++++ + diff --git a/src/docs/asciidoc/v4/_attributes.adoc b/src/docs/asciidoc/v4/_attributes.adoc new file mode 100644 index 0000000..bf10d4b --- /dev/null +++ b/src/docs/asciidoc/v4/_attributes.adoc @@ -0,0 +1,16 @@ +:doctype: book +:idprefix: +:idseparator: - +:toc: left +:toclevels: 4 +:tabsize: 4 +:numbered: +:sectanchors: +:sectnums: +:icons: font +:hide-uri-scheme: +:docinfo: shared,private + +:sc-ext: java +:project-full-name: springdoc-openapi +:all: {asterisk}{asterisk} diff --git a/src/docs/asciidoc/v4/core-properties.adoc b/src/docs/asciidoc/v4/core-properties.adoc new file mode 100644 index 0000000..86b130b --- /dev/null +++ b/src/docs/asciidoc/v4/core-properties.adoc @@ -0,0 +1,64 @@ +[[core-properties]] + +|=== +|Parameter name | Default Value | Description + +|springdoc.api-docs.path | `/v3/api-docs` | `String`, For custom path of the OpenAPI documentation in Json format. +|springdoc.api-docs.enabled | `true` | `Boolean`. To disable the springdoc-openapi endpoint (/v3/api-docs by default). +|springdoc.packages-to-scan | `*`| `List of Strings`. The list of packages to scan (comma separated) +|springdoc.paths-to-match | `/*`| `List of Strings`. The list of paths to match (comma separated) +|springdoc.produces-to-match | `/*`| `List of Strings`. The list of produces mediaTypes to match (comma separated) +|springdoc.headers-to-match | `/*`| `List of Strings`. The list of headers to match (comma separated) +|springdoc.consumes-to-match | `/*`| `List of Strings`. The list of consumes mediaTypes to match (comma separated) +|springdoc.paths-to-exclude | | `List of Strings`. The list of paths to exclude (comma separated) +|springdoc.packages-to-exclude | | `List of Strings`. The list of packages to exclude (comma separated) +|springdoc.default-consumes-media-type | `application/json` | `String`. The default consumes media type. +|springdoc.default-produces-media-type | `*/*` | `String`. The default produces media type. +|springdoc.cache.disabled | `false` | `Boolean`. To disable the springdoc-openapi cache of the calculated OpenAPI. +|springdoc.show-actuator | `false` | `Boolean`. To display the actuator endpoints. +|springdoc.auto-tag-classes | `true` | `Boolean`. To disable the springdoc-openapi automatic tags. +|springdoc.model-and-view-allowed | `false` | `Boolean`. To allow RestControllers with ModelAndView return to appear in the OpenAPI description. +|springdoc.override-with-generic-response | `true` | `Boolean`. When true, automatically adds @ControllerAdvice responses to all the generated responses. +|springdoc.group-configs[0].group | | `String`. The group name +|springdoc.group-configs[0].display-name | | `String`. The display name of the group. +|springdoc.group-configs[0].packages-to-scan | `*`| `List of Strings`. The list of packages to scan for a group (comma separated) +|springdoc.group-configs[0].paths-to-match | `/*`| `List of Strings`. The list of paths to match for a group (comma separated) +|springdoc.group-configs[0].paths-to-exclude | ``| `List of Strings`. The list of paths to exclude for a group (comma separated) +|springdoc.group-configs[0].packages-to-exclude | | `List of Strings`. The list of packages to exclude for a group (comma separated) +|springdoc.group-configs[0].produces-to-match | `/*`| `List of Strings`. The list of produces mediaTypes to match (comma separated) +|springdoc.group-configs[0].consumes-to-match | `/*`| `List of Strings`. The list of consumes mediaTypes to match (comma separated) +|springdoc.group-configs[0].headers-to-match | `/*`| `List of Strings`. The list of headers to match (comma separated) +|springdoc.webjars.prefix | `/webjars` |`String`. To change the webjars prefix that is visible the URL of swagger-ui for spring-webflux. +|springdoc.api-docs.resolve-schema-properties | `false` | `Boolean`. To enable property resolver on @Schema (name, title and description). +|springdoc.remove-broken-reference-definitions | `true` | `Boolean`. To disable removal of broken reference definitions. +|springdoc.writer-with-default-pretty-printer | `false` | `Boolean`. To enable pretty print of the OpenApi specification. +|springdoc.model-converters.deprecating-converter.enabled | `true` | `Boolean`. To disable deprecating model converter. +|springdoc.model-converters.polymorphic-converter.enabled | `true` | `Boolean`. To disable polymorphic model converter. +|springdoc.model-converters.pageable-converter.enabled | `true` | `Boolean`. To disable pageable model converter. +|springdoc.model-converters.sort-converter.enabled | `true` | `Boolean`. To disable Sort converter. +|springdoc.use-fqn | `false` | `Boolean`. To enable fully qualified names. +|springdoc.show-login-endpoint | `false` | `Boolean`. To make spring security login-endpoint visible. +|springdoc.pre-loading-locales | | `List of Strings`. The list of locales to load OpenAPI on application startup (comma separated). If not specified, it will preload with the default Locale. +|springdoc.writer-with-order-by-keys | `false` | `Boolean`. Enable a deterministic/alphabetical ordering. +|springdoc.use-management-port | `false` | `Boolean`. To expose the swagger-ui on the actuator management port. +|springdoc.disable-i18n | `false` | `Boolean`. To disable automatic translation using i18n. +|springdoc.show-spring-cloud-functions | `true` | `Boolean`. To display the spring-cloud-function web endpoints. +|springdoc.enable-groovy | `true` | `Boolean`. To enable Groovy support. +|springdoc.enable-spring-security | `true` | `Boolean`. To enable spring-security support. +|springdoc.enable-kotlin | `true` | `Boolean`. To enable Kotlin support. +|springdoc.enable-hateoas | `true` | `Boolean`. To enable spring-hateoas support. +|springdoc.enable-data-rest | `true` | `Boolean`. To enable spring-data-rest support. +|springdoc.api-docs.version | `openapi_3_1` | `String`. To choose `OpenAPI 3.0` or `OpenAPI 3.1` (using the value `OPENAPI_3_1`). +|springdoc.default-flat-param-object | `false` | `Boolean`. To default flatten parameter. +|springdoc.default-support-form-data | `false` | `Boolean`. To default set parameters to form data when specifying api to accept form data. +|springdoc.nullable-request-parameter-enabled | `true` | `Boolean`. To default Enable Support for nullable request parameters in Kotlin. +|springdoc.show-oauth2-endpoints | `false` | `Boolean`. To make spring security oauth2-endpoint visible. +|springdoc.api-docs.resolve-extensions-properties | `false` | `Boolean`. To enable support of spring property resolver for `@ExtensionProperty`. +|springdoc.enable-default-api-docs | `true` | `Boolean`. To enable default OpenAPI endpoint `/v3/api-docs`. +|springdoc.trim-kotlin-indent | `false` | `Boolean`. Adjust indentation when parsing the `@Operation` annotation in Kotlin. +|springdoc.allowed-locales | | `List of Strings`. The list of allowed locales for OpenAPI (comma separated, for example `US,fr-CA`). +|springdoc.enable-extra-schemas | `true` | `Boolean`. To enable default support for extra Schemas, from `java.time` package like `LocalTime`, `Duration`, but also other Java classes like `java.util.Locale` or `java.nio.charset.Charset` +|springdoc.explicit-object-schema | `false` | `Boolean`. Set explicit-object-schema to `true` to always include `type: object` in the schema, or to `false` to omit `type: object`. +|springdoc.use-arbitrary-schemas | `false` | `Boolean`. When set to `true`, schemas without a defined type will be deserialized as an `ArbitrarySchema` (with no type), instead of an `ObjectSchema` with `type: object`. +|=== + diff --git a/src/docs/asciidoc/v4/demos.adoc b/src/docs/asciidoc/v4/demos.adoc new file mode 100644 index 0000000..e33d9a2 --- /dev/null +++ b/src/docs/asciidoc/v4/demos.adoc @@ -0,0 +1,30 @@ +[[demos]] +== Springdoc-openapi Demos + +=== springdoc applications demos +* link:https://demos1.springdoc.org/demo-spring-boot-webmvc[Demo Spring Boot 4 Web MVC with OpenAPI 3, window="_blank"] +* link:https://demos1.springdoc.org/demo-spring-boot-webflux/swagger-ui.html[Demo Spring Boot 4 WebFlux with OpenAPI 3, window="_blank"] +* link:https://demos1.springdoc.org/demo-spring-boot-webflux-functional/swagger-ui.html[Demo Spring Boot 4 WebFlux with Functional endpoints OpenAPI 3, window="_blank"] +* link:https://demos1.springdoc.org/demo-spring-hateoas[Demo Spring Boot 4 and Spring Hateoas with OpenAPI 3, window="_blank"] +* link:https://demos1.springdoc.org/spring-cloud-function-webmvc[Demo Spring Boot 4 and Spring Cloud Function Web MVC, window="_blank"] +* link:https://demos1.springdoc.org/spring-cloud-function-webflux/swagger-ui.html[Demo Spring Boot 4 and Spring Cloud Function WebFlux, window="_blank"] +* link:https://demos1.springdoc.org/demo-microservices/swagger-ui.html[Demo Spring Boot 4 and Spring Cloud Gateway, window="_blank"] + +image::img/pets.png[pets.png] + +=== Source code of the Demo Applications +* link:https://github.com/springdoc/springdoc-openapi-demos/tree/4.x[https://github.com/springdoc/springdoc-openapi-demos/tree/4.x, window="_blank"] + +++++ + + + +++++ diff --git a/src/docs/asciidoc/v4/docinfo-footer.html b/src/docs/asciidoc/v4/docinfo-footer.html new file mode 100644 index 0000000..e69de29 diff --git a/src/docs/asciidoc/v4/docinfo.html b/src/docs/asciidoc/v4/docinfo.html new file mode 100644 index 0000000..112e384 --- /dev/null +++ b/src/docs/asciidoc/v4/docinfo.html @@ -0,0 +1,15 @@ + + + + + \ No newline at end of file diff --git a/src/docs/asciidoc/v4/faq.adoc b/src/docs/asciidoc/v4/faq.adoc new file mode 100644 index 0000000..bd8ae82 --- /dev/null +++ b/src/docs/asciidoc/v4/faq.adoc @@ -0,0 +1,1109 @@ +[[faq]] +== F.A.Q + +=== How can I define multiple OpenAPI definitions in one Spring Boot project? +You can define your own groups of API based on the combination of: API paths and packages to scan. Each group should have a unique `groupName`. +The OpenAPI description of this group, will be available by default on: + +* `\http://server:port/context-path/v3/api-docs/groupName` + +To enable the support of multiple OpenAPI definitions, a bean of type `GroupedOpenApi` needs to be defined. + +For the following Group definition(based on package path), the OpenAPI description URL will be : /v3/api-docs/**stores** + +[source,java] +---- +@Bean +public GroupedOpenApi storeOpenApi() { + String paths[] = {"/store/**"}; + return GroupedOpenApi.builder().group("stores").pathsToMatch(paths) + .build(); +} +---- + +For the following Group definition (based on package name), the OpenAPI description URL will be: /v3/api-docs/**users** + +[source,java] +---- +@Bean +public GroupedOpenApi userOpenApi() { + String packagesToscan[] = {"test.org.springdoc.api.app68.api.user"}; + return GroupedOpenApi.builder().group("users").packagesToScan(packagesToscan) + .build(); +} +---- + +For the following Group definition(based on path), the OpenAPI description URL will be: /v3/api-docs/**pets** + +[source,java] +---- +@Bean +public GroupedOpenApi petOpenApi() { + String paths[] = {"/pet/**"}; + return GroupedOpenApi.builder().group("pets").pathsToMatch(paths) + .build(); +} +---- + +For the following Group definition (based on package name and path), the OpenAPI description URL will be: /v3/api-docs/**groups** + +[source,java] +---- +@Bean +public GroupedOpenApi groupOpenApi() { + String paths[] = {"/v1/**"}; + String packagesToscan[] = {"test.org.springdoc.api.app68.api.user", "test.org.springdoc.api.app68.api.store"}; + return GroupedOpenApi.builder().group("groups").pathsToMatch(paths).packagesToScan(packagesToscan) + .build(); +} +---- + +For more details about the usage, you can have a look at the following sample Test: + +* link:https://github.com/springdoc/springdoc-openapi/tree/spring-boot-4/springdoc-openapi-tests/springdoc-openapi-actuator-webmvc-tests/src/test/java/test/org/springdoc/api/app68[https://github.com/springdoc/springdoc-openapi/tree/spring-boot-4/springdoc-openapi-tests/springdoc-openapi-actuator-webmvc-tests/src/test/java/test/org/springdoc/api/app68, window="_blank"] + +=== How can I configure Swagger UI? +* The support of the swagger official properties is available on `springdoc-openapi`. See link:https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/[Official documentation, window="_blank"]. + +* You can use the same swagger properties in the documentation as Spring Boot properties. + +NOTE: All these properties should be declared with the following prefix: `springdoc.swagger-ui` + +=== How can I filter the resources documented in the output specification by the provided group? +* You can use the standard `swagger-ui` property filter. +[source,properties] +---- +springdoc.swagger-ui.filter=group-a +---- + +=== How can I disable/enable Swagger UI generation based on env variable? +* This property helps you disable only the UI. +[source,properties] +---- +springdoc.swagger-ui.enabled=false +---- +=== How can I control the default expansion setting for the operations and tags, in the Swagger UI , +* You can set this property in your application.yml like so for example: +[source,properties] +---- +springdoc.swagger-ui.doc-expansion= none +---- + +=== How can I change the layout of the `swagger-ui`? +* For layout options, you can use swagger-ui configuration options. For example: +[source,properties] +---- +springdoc.swagger-ui.layout=BaseLayout +---- + +=== How can I sort endpoints alphabetically? +* You can use the following `springdoc-openapi` properties: +[source,properties] +---- +#For sorting endpoints alphabetically +springdoc.swagger-ui.operationsSorter=alpha +#For sorting tags alphabetically +springdoc.swagger-ui.tagsSorter=alpha +---- + +=== How can I disable the try it out button? +* You have to set the following property: +[source,properties] +---- +springdoc.swagger-ui.supportedSubmitMethods=get, put, post, delete, options, head, patch, trace +---- + +=== How can I add Reusable Enums ? +* You should add `@Schema(enumAsRef = true)` on your enum. + +=== How can i apply `enumAsRef = true` to all enums ? +* Declare the following property: +[source,java] +---- +static { + io.swagger.v3.core.jackson.ModelResolver.enumsAsRef = true; +} +---- + +=== How can I explicitly set which paths to filter? +* You can set list of paths to include using the following property: +[source,properties] +---- +springdoc.pathsToMatch=/v1, /api/balance/** +---- + +=== How can I explicitly set which packages to scan? +* You can set list of packages to include using the following property: +[source,properties] +---- +springdoc.packagesToScan=package1, package2 +---- + +=== How can I set Swagger properties programmatically? + +These can be set by creating a `swaggerUiConfig` bean as follows: +[source,kotlin] +---- +@Bean +@Primary +fun swaggerUiConfig(config: SwaggerUiConfigProperties): SwaggerUiConfigProperties { + config.showCommonExtensions = true + config.queryConfigEnabled = true + return config +} +---- + +=== How can I ignore some field of model ? +* You can use the following annotation on the top of the field that you want to hide: +* `@Schema(hidden = true)` + +=== How can I ignore `@AuthenticationPrincipal` parameter from spring-security ? +* A solution workaround would be to use: `@Parameter(hidden = true)` +* The projects that use `spring-boot-starter-security` or `spring-security-oauth2-authorization-server` should use: + +- `springdoc-openapi-starter-webmvc-api` if they depend on `spring-boot-starter-web` and they only need the access to the OpenAPI endpoints. +- OR `springdoc-openapi-starter-webmvc-ui`, if they depend on `spring-boot-starter-web` and they also need the access to the swagger-ui. +- OR `springdoc-openapi-starter-webflux-api` if they depend on `spring-boot-starter-webflux` and they only the access to the OpenAPI endpoints. +- OR `springdoc-openapi-starter-webflux-ui`, if they depend on `spring-boot-starter-webflux` and they also need the access to the swagger-ui. + + + +=== Is there a Gradle plugin available? +* Yes. More details are available, in the link:https://springdoc.org/#gradle-plugin[gradle plugin] section. + +=== How can I hide a parameter from the documentation ? +* You can use `@Parameter(hidden = true)` + +=== Is `@Parameters` annotation supported ? +* Yes + +=== Does `springdoc-openapi` support Jersey? +* If you are using JAX-RS and as implementation Jersey (`@Path` for example), we do not support it. +* We only support exposing Rest Endpoints using Spring managed beans (`@RestController` for example). +* You can have a look at swagger-jaxrs2 project: +** link:https://github.com/swagger-api/swagger-samples/tree/2.0/java/java-jersey2-minimal[https://github.com/swagger-api/swagger-samples/tree/2.0/java/java-jersey2-minimal, window="_blank"] + +=== Can `springdoc-openapi` generate API only for `@RestController`? +* `@RestController` is equivalent to `@Controller` + `@RequestMapping` on the type level. +* For some legacy apps, we are constrained to still support both. +* If you need to hide the `@Controller` on the type level, in this case, you can use: `@Hidden` on controller level. +* Please note this annotation can be also used to hide some methods from the generated documentation. + +=== Are the following validation annotations supported : `@NotEmpty` `@NotBlank` `@PositiveOrZero` `@NegativeOrZero`? +* Yes + +=== How can I map `Pageable` (spring-data-commons) object to correct URL-Parameter in Swagger UI? + +The support for Pageable of spring-data-commons is available out-of-the box since `springdoc-openapi v1.6.0`. +For this, you have to combine `@ParameterObject` annotation with the `Pageable` type. + + +Before `springdoc-openapi v1.6.0`: + +* You can use as well `@ParameterObject` instead of `@PageableAsQueryParam` for HTTP `GET` methods. + +[source,java] +---- +static { + getConfig().replaceParameterObjectWithClass(org.springframework.data.domain.Pageable.class, Pageable.class) + .replaceParameterObjectWithClass(org.springframework.data.domain.PageRequest.class, Pageable.class); +} +---- + +* Another solution, is to configure Pageable manually: + - you will have to declare the explicit mapping of Pageable fields as Query Params and add the `@Parameter(hidden = true) Pageable pageable` on your pageable parameter. + - You should also, declare the annotation `@PageableAsQueryParam` provided by `springdoc-openapi` on the method level, or declare your own if need to define your custom description, defaultValue, ... + +If you want to disable the support of spring Pageable Type, you can use: +[source,properties] +---- +springdoc.model-converters.pageable-converter.enabled=false +---- + +NOTE: The property `springdoc.model-converters.pageable-converter.enabled` is only available since v1.5.11+ + +=== How can I generate enums in the generated description? +* You could add a property `allowableValues`, to `@Parameter`. For example: + +[source,java] +---- +@GetMapping("/example") +public Object example(@Parameter(name ="json", schema = @Schema(description = "var 1",type = "string", allowableValues = {"1", "2"})) +String json) { + return null; +} +---- + +* or you could override `toString` on your enum: + +[source,java] +---- +@Override +@JsonValue +public String toString() { + return String.valueOf(action); +} +---- + +=== How can I deploy `springdoc-openapi-starter-webmvc-ui` behind a reverse proxy? +* If your application is running behind a proxy, a load-balancer or in the cloud, the request information (like the host, port, scheme…​) might change along the way. Your application may be running on `10.10.10.10:8080`, but HTTP clients should only see `example.org`. + +* link:https://tools.ietf.org/html/rfc7239[RFC7239 "Forwarded Headers", window="_blank"] defines the Forwarded HTTP header; proxies can use this header to provide information about the original request. You can configure your application to read those headers and automatically use that information when creating links and sending them to clients in HTTP 302 responses, JSON documents or HTML pages. There are also non-standard headers, like `X-Forwarded-Host`, `X-Forwarded-Port`, `X-Forwarded-Proto`, `X-Forwarded-Ssl`, and `X-Forwarded-Prefix`. + +* If the proxy adds the commonly used `X-Forwarded-For` and `X-Forwarded-Proto headers`, setting server.forward-headers-strategy to NATIVE is enough to support those. With this option, the Web servers themselves natively support this feature; you can check their specific documentation to learn about specific behavior. + +* You need to make sure the following header is set in your reverse proxy configuration: `X-Forwarded-Prefix` +* For example, using Apache 2, configuration: +[source,properties] +---- +RequestHeader set X-Forwarded-Prefix "/custom-path" +---- +* Then, in your Spring Boot application make sure your application handles this header: `X-Forwarded-For`. There are two ways to achieve this: +[source,properties] +---- +server.use-forward-headers=true +---- +* If this is not enough, Spring Framework provides a `ForwardedHeaderFilter`. You can register it as a Servlet Filter in your application by setting server.forward-headers-strategy is set to FRAMEWORK. +* Since Spring Boot 2.2, this is the new property to handle reverse proxy headers: + +[source,properties] +---- +server.forward-headers-strategy=framework +---- + +* And you can add the following bean to your application: + +[source,java] +---- +@Bean +ForwardedHeaderFilter forwardedHeaderFilter() { + return new ForwardedHeaderFilter(); +} +---- + +* If you need to manually adjust the URL displayed in the Swagger UI, implement the `ServerBaseUrlCustomizer` interface. This might be necessary to remove the port number, for example. + +[source,java] +---- +@Bean +public class CustomServerBaseUrlCustomizer implements ServerBaseUrlCustomizer { + @Override + public String customize(String serverBaseUrl) { + try { + URL url = new URL(serverBaseUrl); + if (url.getHost().contains(".com")) { + serverBaseUrl = new URL(url.getProtocol(),url.getHost(),url.getFile()).toString(); + } + } catch (MalformedURLException ex) { + // nothing we can do + } + + return serverBaseUrl; + } +} +---- + +=== Is `@JsonView` annotations in Spring MVC APIs supported? +* Yes + +=== Adding `springdoc-openapi-starter-webmvc-ui` dependency breaks my `public/index.html` welcome page +* If you already have static content on your root, and you don't want it to be overridden by `springdoc-openapi-starter-webmvc-ui` configuration, you can just define a custom configuration of the `swagger-ui`, in order not to override the configuration of your files from in your context-root: +* For example use: +[source,properties] +---- +springdoc.swagger-ui.path= /swagger-ui/api-docs.html +---- + +=== How can I test the Swagger UI? +* You can have a look on this sample test of the UI: +** link:https://github.com/springdoc/springdoc-openapi/blob/spring-boot-4/springdoc-openapi-starter-webmvc-ui/src/test/java/test/org/springdoc/ui/app1/SpringDocApp1Test.java[https://github.com/springdoc/springdoc-openapi/blob/spring-boot-4/springdoc-openapi-starter-webmvc-ui/src/test/java/test/org/springdoc/ui/app1/SpringDocApp1Test.java, window="_blank"] + +=== How can I customise the OpenAPI object ? +* You can write your own implementation of `OpenApiCustomizer`. +* An example is available on: +** link:https://github.com/springdoc/springdoc-openapi/blob/spring-boot-4/springdoc-openapi-starter-webflux-api/src/test/java/test/org/springdoc/api/app39/SpringDocTestApp.java[https://github.com/springdoc/springdoc-openapi/blob/spring-boot-4/springdoc-openapi-starter-webflux-api/src/test/java/test/org/springdoc/api/app39/SpringDocTestApp.java, window="_blank"] + +[source,java] +---- +@Bean +public OpenApiCustomizer consumerTypeHeaderOpenAPICustomizer() { +return openApi -> openApi.getPaths().values().stream().flatMap(pathItem -> pathItem.readOperations().stream()) + .forEach(operation -> operation.addParametersItem(new HeaderParameter().$ref("#/components/parameters/myConsumerTypeHeader"))); +} +---- + +NOTE: This bean `OpenApiCustomizer` will be applied to the Default OpenAPI only. + +If you need the `OpenApiCustomizer` to applied to `GroupedOpenApi` as well, then use `GlobalOpenApiCustomizer` instead. + +=== How can I return an empty content as response? +* It is be possible to handle as return an empty content as response using, one of the following syntaxes: +* `content = @Content` +* `content = @Content(schema = @Schema(hidden = true))` +* For example: + +[source,java] +---- +@Operation(summary = "Get thing", responses = { + @ApiResponse(description = "Successful Operation", responseCode = "200", content = @Content(mediaType = "application/json", schema = @Schema(implementation = String.class))), + @ApiResponse(responseCode = "404", description = "Not found", content = @Content), + @ApiResponse(responseCode = "401", description = "Authentication Failure", content = @Content(schema = @Schema(hidden = true))) }) +@RequestMapping(path = "/testme", method = RequestMethod.GET) +ResponseEntity testme() { + return ResponseEntity.ok("Hello"); +} +---- + +=== How are endpoints with multiple consuming media types supported? +* An overloaded method on the same class, with the same HTTP Method and path, will have as a result, only one OpenAPI Operation generated. +* In addition, it's recommended to have the `@Operation` in the level of one of the overloaded methods. Otherwise it might be overridden if it's declared many times within the same overloaded method. + +=== How can I get yaml and json (OpenAPI) in compile time? +* You can use `springdoc-openapi-maven-plugin` for this functionality: +** link:https://github.com/springdoc/springdoc-openapi-maven-plugin.git[https://github.com/springdoc/springdoc-openapi-maven-plugin.git, window="_blank"] +* You can customise the output directory (property outputDir): The default value is: ${project.build.directory} + +=== What are the ignored types in the documentation? +* `Principal`, `Locale`, `HttpServletRequest` and `HttpServletResponse` and other injectable parameters supported by Spring MVC are excluded. +* Full documentation here: +** link:https://docs.spring.io/spring/docs/5.1.x/spring-framework-reference/web.html#mvc-ann-arguments[https://docs.spring.io/spring/docs/5.1.x/spring-framework-reference/web.html#mvc-ann-arguments, window="_blank"] + +=== How can i disable ignored types: + +If you don't want to ignore the types `Principal`, `Locale`, `HttpServletRequest`, and others,: + +[source,java] +---- +SpringDocUtils.getConfig().removeRequestWrapperToIgnore(HttpServletRequest.class) +---- + + +=== How do I add authorization header in requests? +* You should add the `@SecurityRequirement` tags to your protected APIs. +* For example: +---- +@Operation(security = { @SecurityRequirement(name = "bearer-key") }) +---- +* And the security definition sample: + +[source,java] +---- +@Bean + public OpenAPI customOpenAPI() { + return new OpenAPI() + .components(new Components() + .addSecuritySchemes("bearer-key", + new SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("bearer").bearerFormat("JWT"))); +} +---- + +=== Differentiation to Springfox project + +* OAS 3 was released in July 2017, and there was no release of `springfox` to support OAS 3. +`springfox` covers for the moment only swagger 2 integration with Spring Boot. The latest release date is June 2018. So, in terms of maintenance there is a big lack of support lately. + +* We decided to move forward and share the library that we already used on our internal projects, with the community. +* The biggest difference with `springfox`, is that we integrate new features not covered by `springfox`: + +* The integration between Spring Boot and OpenAPI 3 standard. +* We rely on on `swagger-annotations` and `swagger-ui` only official libraries. +* We support new features on Spring 5, like `spring-webflux` with annotated and functional style. +* We do our best to answer all the questions and address all issues or enhancement requests + +=== How do I migrate to OpenAPI 3 with springdoc-openapi +* There is no relation between `springdoc-openapi` and `springfox`.If you want to migrate to OpenAPI 3: +* Remove all the dependencies and the related code to springfox +* Add `springdoc-openapi-starter-webmvc-ui` dependency +* If you don't want to serve the UI from your root path or there is a conflict with an existing configuration, you can just change the following property: +[source,properties] +---- +springdoc.swagger-ui.path=/you-path/swagger-ui.html +---- + +=== How can I set a global header? +* You may have global parameters with Standard OpenAPI description. +* If you need the definitions to appear globally (within every group), no matter if the group fulfills the conditions specified on the GroupedOpenApi , you can use OpenAPI Bean. +* You can define common parameters under parameters in the global components section and reference them elsewhere via `$ref`. You can also define global header parameters. +* For this, you can override to OpenAPI Bean, and set the global headers or parameters definition on the components level. + +[source,java] +---- +@Bean +public OpenAPI customOpenAPI(@Value("${springdoc.version}") String appVersion) { + return new OpenAPI() + .components(new Components().addSecuritySchemes("basicScheme", new SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("basic")) + .addParameters("myHeader1", new Parameter().in("header").schema(new StringSchema()).name("myHeader1")).addHeaders("myHeader2", new Header().description("myHeader2 header").schema(new StringSchema()))) + .info(new Info() + .title("Petstore API") + .version(appVersion) + .description("This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.") + .termsOfService("http://swagger.io/terms/") + .license(new License().name("Apache 2.0").url("http://springdoc.org"))); +} +---- + +=== Are Callbacks supported? +* Yes + +=== How can I define SecurityScheme ? +* You can use: `@SecurityScheme` annotation. +* Or you can define it programmatically, by overriding OpenAPI Bean: + +[source,java] +---- + @Bean + public OpenAPI customOpenAPI(@Value("${springdoc.version}") String appVersion) { + return new OpenAPI() + .components(new Components().addSecuritySchemes("basicScheme", + new SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("basic"))) + info(new Info().title("SpringShop API").version(appVersion) + .license(new License().name("Apache 2.0").url("http://springdoc.org"))); + } +---- + +=== How can I hide an operation or a controller from documentation ? +* You can use `@io.swagger.v3.oas.annotations.Hidden` annotation at `@RestController`, `@RestControllerAdvice` and method level +* The `@Hidden` annotation on exception handler methods, is considered when building generic (error) responses from `@ControllerAdvice` exception handlers. +* Or use: `@Operation(hidden = true)` + + + + +=== How to configure global security schemes? +* For global SecurityScheme, you can add it inside your own OpenAPI definition: + +[source,java] +---- +@Bean +public OpenAPI customOpenAPI() { + return new OpenAPI().components(new Components() + .addSecuritySchemes("basicScheme", new SecurityScheme() + .type(SecurityScheme.Type.HTTP).scheme("basic"))).info(new Info().title("Custom API") + .version("100")).addTagsItem(new Tag().name("mytag")); +} +---- + +=== Can I use spring property with swagger annotations? +* The support of spring property resolver for `@Info`: `title` * `description` * `version` * `termsOfService` +* The support of spring property resolver for `@Info.license`: `name` * `url` +* The support of spring property resolver for `@Info.contact`: `name` * `email` * `url` +* The support of spring property resolver for `@Operation`: `description` * `summary` +* The support of spring property resolver for `@Parameter`: `description` * `name` +* The support of spring property resolver for `@ApiResponse`: `description` +* Its also possible to declare security URLs for `@OAuthFlow`: `openIdConnectUrl` * `authorizationUrl` * `refreshUrl` * `tokenUrl` +* The support of spring property resolver for `@Schema`: `name` * `title` * `description` , by setting `springdoc.api-docs.resolve-schema-properties` to `true` +* The support of spring property resolver for `@ExtensionProperty` by setting `springdoc.api-docs.resolve-extensions-properties` to `true` + +=== How is server URL generated ? +* Generating automatically server URL may be useful, if the documentation is not present. +* If the server annotations are present, they will be used instead. + +=== How can I disable springdoc-openapi cache? +* By default, the OpenAPI description is calculated once, and then cached. +* Sometimes the same swagger-ui is served behind internal and external proxies. some users want the server URL, to be computed on each http request. +* In order to disable springdoc cache, you will have to set the following property: +[source,properties] +---- +springdoc.cache.disabled= true +---- + +=== How can I expose the mvc api-docs endpoints without using the `swagger-ui`? +* You should use the `springdoc-openapi-core` dependency only: + +[source,xml] +---- + + org.springdoc + springdoc-openapi-starter-webmvc-api + latest.version + +---- +=== How can I disable `springdoc-openapi` endpoints ? +* Use the following property: +---- +springdoc.api-docs.enabled=false +---- + +=== How can I hide Schema of the the response ? + +* To hide the response element, using `@Schema` annotation, as follows, at operation level: + +---- +@Operation(responses = @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(hidden = true)))) +---- + +* Or directly at `@ApiResponses` level: + +---- +@ApiResponses(value = {@ApiResponse(responseCode = "200", content = @Content(schema = @Schema(hidden = true))) }) +OR +@ApiResponse(responseCode = "404", description = "Not found", content = @Content) +---- + +=== What is the URL of the `swagger-ui`, when I set a different context-path? + +* If you use different context-path: +[source,properties] +---- +server.servlet.context-path= /foo +---- +* The `swagger-ui` will be available on the following URL: +** `\http://server:port/foo/swagger-ui.html` + +=== Can I customize OpenAPI object programmatically? + +* You can Define your own OpenAPI Bean: If you need the definitions to appear globally (within every group), no matter if the group fulfills the conditions specified on the GroupedOpenApi , you can use OpenAPI Bean. + +[source,java] +---- +@Bean +public OpenAPI customOpenAPI(@Value("${springdoc.version}") String appVersion) { + return new OpenAPI() + .components(new Components().addSecuritySchemes("basicScheme", + new SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("basic"))) + .info(new Info().title("SpringShop API").version(appVersion) + .license(new License().name("Apache 2.0").url("http://springdoc.org"))); +} +---- +* If you need the definitions to appear within a specific group, and respect the conditions specified on the GroupedOpenApi, you can add OpenApiCustomizer to your GroupedOpenApi definition. + +[source,java] +---- +GroupedOpenApi.builder().group("users").pathsToMatch(paths).packagesToScan(packagedToMatch).addOpenApiCustomizer(customerGlobalHeaderOpenApiCustomizer()) + .build() + +@Bean +public OpenApiCustomizer customerGlobalHeaderOpenApiCustomizer() { + return openApi -> openApi.path("/foo", + new PathItem().get(new Operation().operationId("foo").responses(new ApiResponses() + .addApiResponse("default",new ApiResponse().description("") + .content(new Content().addMediaType("fatz", new MediaType())))))); +} +---- + + +=== Where can I find the source code of the demo applications? +* The source code of the application is available at the following GitHub repository: +** link:https://github.com/springdoc/springdoc-openapi-demos[https://github.com/springdoc/springdoc-openapi-demos, window="_blank"] + +=== Does this library supports annotations from interfaces? +* Yes + +=== What is the list of the excluded parameter types? +* link:https://docs.spring.io/spring/docs/5.1.x/spring-framework-reference/web.html#mvc-ann-arguments[https://docs.spring.io/spring/docs/5.1.x/spring-framework-reference/web.html#mvc-ann-arguments, window="_blank"]. + +=== Is file upload supported ? +* The library supports the main file types: `MultipartFile`, `@RequestPart`, `FilePart` +* You can upload a file as follows: + +[source,java] +---- +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Encoding; +import io.swagger.v3.oas.annotations.parameters.RequestBody; + +@PostMapping(value = "/upload", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}) +public ResponseEntity upload(@Parameter(description = "file") final MultipartFile file) { + return null; +} + +@PostMapping(value = "/uploadFileWithQuery", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}) +public ResponseEntity uploadFileWithQuery(@Parameter(description = "file") @RequestPart("file") final MultipartFile file, + @Parameter(description = "An extra query parameter") @RequestParam String name) { + return null; +} + +@PostMapping(value = "/uploadFileWithJson", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}, produces = { + MediaType.APPLICATION_JSON_VALUE}) +public ResponseEntity uploadFileWithJson( + @RequestBody(content = @Content(encoding = @Encoding(name = "jsonRequest", contentType = MediaType.APPLICATION_JSON_VALUE))) + @Parameter(description = "An extra JSON payload sent with file") @RequestPart("jsonRequest") final JsonRequest jsonRequest, + @RequestPart("file") final MultipartFile file) { + return null; +} +---- + +=== Can I use `@Parameter` inside `@Operation` annotation? +* Yes, it's supported + +=== Why my parameter is marked as required? +* Any `@GetMapping` parameters is marked as required, even if `@RequestParam` is missing. +* You can add `@Parameter(required=false)` annotation if you need different behaviour. +* Query parameters with `defaultValue` specified are marked as required. + +=== How are overloaded methods with the same endpoints, but with different parameters +* `springdoc-openapi` renders these methods as a single endpoint. It detects the overloaded endpoints, and generates parameters.schema.oneOf. + +=== What is a proper way to set up Swagger UI to use provided spec.yml? +* With this property, all the `springdoc-openapi` auto-configuration beans are disabled: +[source,properties] +---- +springdoc.api-docs.enabled=false +---- +* Then enable the minimal Beans configuration, by adding this Bean: + +[source,java] +---- +@Bean +SpringDocConfiguration springDocConfiguration(){ + return new SpringDocConfiguration(); +} + +@Bean +SpringDocConfigProperties springDocConfigProperties() { + return new SpringDocConfigProperties(); +} + +@Bean +ObjectMapperProvider objectMapperProvider(SpringDocConfigProperties springDocConfigProperties){ + return new ObjectMapperProvider(springDocConfigProperties); +} +---- + +* Then configure, the path of your custom UI yaml file. +[source,properties] +---- +springdoc.swagger-ui.url=/api-docs.yaml +---- + +=== Is there a way to send authorization header through the @Parameter tag? +* The OpenAPI 3 specification does not allow explicitly adding Authorization header. +`Note: Header parameters named Accept, Content-Type and Authorization are not allowed. To describe these headers` +* For more information, you can read: +** link:https://swagger.io/docs/specification/describing-parameters/#header-parameters[https://swagger.io/docs/specification/describing-parameters/#header-parameters, window="_blank"] + +=== My Rest Controller using @Controller annotation is ignored? +* This is the default behaviour if your `@Controller` doesn't have annotation `@ResponseBody` +* You can change your controllers to `@RestControllers`. Or add `@ResponseBody` + `@Controller`. +* If its not possible, you can configure springdoc to scan you additional controller using SpringDocUtils. For example: + +[source,java] +---- +static { + SpringDocUtils.getConfig().addRestControllers(HelloController.class); +} +---- + +=== How can I define groups using application.yml? +* You can load groups dynamically using spring-boot configuration files. +* Note that, for this usage, you don't have to declare the **GroupedOpenApi** Bean. +* You need to declare the following properties, under the prefix **springdoc.group-configs**. +* For example: +[source,properties] +---- +springdoc.group-configs[0].group=users +springdoc.group-configs[0].paths-to-match=/user/** +springdoc.group-configs[0].packages-to-scan=test.org.springdoc.api +---- +* The list of properties under this prefix, are available here: +** link:index.html#properties[springdoc-openapi-properties] + +=== How can I extract fields from parameter object ? +* You can use springdoc annotation @ParameterObject. +* Request parameter annotated with @ParameterObject will help adding each field of the parameter as a separate request parameter. +* This is compatible with Spring MVC request parameters mapping to POJO object. +* This annotation does not support nested parameter objects. +* POJO object must contain getters for fields with mandatory prefix `get`. Otherwise, the swagger documentation will not show the fields of the annotated entity. + +=== How can I use the last `springdoc-openapi` SNAPSHOT ? +* For testing purposes only, you can test temporarily using the last `springdoc-openapi` SNAPSHOT +* To achieve that, configure your pom.xml file with the following `` section: + +[source,xml] +---- + + + Central Portal Snapshots + central-portal-snapshots + https://central.sonatype.com/repository/maven-snapshots/ + + false + + + true + + + +---- + +=== How can I use enable `springdoc-openapi` MonetaryAmount support ? +* If an application wants to enable the `springdoc-openapi` support, it declares: + +[source,java] +---- +SpringDocUtils.getConfig().replaceWithClass(MonetaryAmount.class, org.springdoc.core.converters.models.MonetaryAmount.class); +---- + +* Another solution, without using springdoc-openapi MonetaryAmount, would be: + +[source,java] +---- +SpringDocUtils.getConfig().replaceWithSchema(MonetaryAmount.class, new ObjectSchema() + .addProperties("amount", new NumberSchema()).example(99.96) + .addProperties("currency", new StringSchema().example("USD"))); +---- + +=== How can i aggregate external endpoints (exposing OPENAPI 3 spec) inside one single application? +The properties `springdoc.swagger-ui.urls.*`, are suitable to configure external (/v3/api-docs url). +For example if you want to agreagte all the endpoints of other services, inside one single application. +IMPORTANT: Don't forget that CORS needs to be enabled as well. + +=== How can use custom json/yml file instead of generated one ? +If your file open-api.json, contains the OpenAPI documentation in OpenAPI 3 format. +Then simply declare: The file name can be anything you want, from the moment your declaration is consistent yaml or json OpenAPI Spec. +[source,properties] +---- + springdoc.swagger-ui.url=/open-api.json +---- + +Then the file open-api.json, should be located in: src/main/resources/static +No additional configuration is needed. + +=== How can i enable CSRF support? +If you are using standard headers.( For example using spring-security headers) +If the CSRF Token is required, swagger-ui automatically sends the new XSRF-TOKEN during each HTTP REQUEST. + +If your XSRF-TOKEN isn't standards-based, you can use a requestInterceptor to manually capture and attach the latest xsrf token to requests programmatically via spring resource transformer: + +* link:https://github.com/swagger-api/swagger-ui/blob/master/docs/usage/configuration.md#requestinterceptor[https://github.com/swagger-api/swagger-ui/blob/main/docs/usage/configuration.md#requestinterceptor, window="_blank"] + +Starting from release v1.4.4 of springdoc-openapi, a new property is added to enable CSRF support, while using standard header names: +[source,properties] +---- +springdoc.swagger-ui.csrf.enabled=true +---- + +=== How can i disable the default swagger petstore URL? +You can use the following property: +[source,properties] +---- +springdoc.swagger-ui.disable-swagger-default-url=true +---- + +=== Is @PageableDefault supported, to enhance the OpenAPI 3 docuementation? +Yes, you can use it in conjunction with `@ParameterObject` annotation. +Also, the spring-boot `spring.data.web.*` and `spring.data.rest.default.*` properties are supported since v1.4.5 + +=== How can i make spring security login-endpoint visible ? +You can use the following property: +[source,properties] +---- +springdoc.show-login-endpoint=true +---- + +=== How can i show schema definitions even the schema is not referenced? +You can use the following property: +[source,properties] +---- +springdoc.remove-broken-reference-definitions=false +---- + +=== How to override @Deprecated? +The whole idea of `springdoc-openapi` is to get your documentation the closest to the code, with minimal code changes. +If the code contains `@Deprecated`, `sprindoc-openapi` will consider its schema as Deprecated as well. +If you want to declare a field on swagger as non deprecated, even with the java code, the field contains `@Depreacted`, +You can use the following property that is available since release v1.4.3: +[source,properties] +---- +springdoc.model-converters.deprecating-converter.enabled=false +---- + +=== How can i display a method that returns ModelAndView? + +You can use the following property: +[source,properties] +---- +springdoc.model-and-view-allowed=true +---- + + +=== How can i have pretty-printed output of the OpenApi specification? + +You can use the following property: +[source,properties] +---- +springdoc.writer-with-default-pretty-printer=true +---- + +=== How can i define different schemas for the same class? +Complex objects are always resolved as a reference to a schema defined in components. +For example let's consider a `Instance` class with an `workAddress` and `homeAddress` attribute of type `Address`: + +[source,java] +---- +public class PersonDTO { + + @JsonProperty + private String email; + + @JsonProperty + private String firstName; + + @JsonProperty + private String lastName; + + @Schema(ref = "WorkAddressSchema") + @JsonProperty + private Address workAddress; + + @Schema(ref = "HomeAddressSchema") + @JsonProperty + private Address homeAddress; + +} + +public class Address { + + @JsonProperty + private String addressName; + +} +---- + +If you want to define two different schemas for this class, you can set up 2 different schemas as follow: + +[source,java] +---- +@Bean +public OpenAPI customOpenAPI() { +return new OpenAPI().components(new Components() +.addSchemas("WorkAddressSchema", getSchemaWithDifferentDescription(Address.class, "work Address" )) +.addSchemas("HomeAddressSchema", getSchemaWithDifferentDescription(Address.class, "home Address" ))); +} + +private Schema getSchemaWithDifferentDescription(Class className, String description){ +ResolvedSchema resolvedSchema = ModelConverters.getInstance() +.resolveAsResolvedSchema( +new AnnotatedType(className).resolveAsRef(false)); +return resolvedSchema.schema.description(description); +} +---- + +=== How can i define different description for a class attribute depending on usage? +For example let's consider a `Instance` class with an `email` attribute: + +[source,java] +---- +public class PersonDTO { + + @JsonProperty + private String email; + + @JsonProperty + private String firstName; + + @JsonProperty + private String lastName; + + +} +---- + +If you want to define two different description for the `email`, you can set up 2 different schemas as follow: + +[source,java] +---- +@Bean +public OpenAPI customOpenAPI() { +return new OpenAPI().components(new Components() +.addSchemas("PersonDTO1", getFieldSchemaWithDifferentDescription(PersonDTO.class, "work email" )) +.addSchemas("PersonDTO2", getFieldSchemaWithDifferentDescription(PersonDTO.class, "home email" ))); +} + +private Schema getFieldSchemaWithDifferentDescription(Class className, String description){ + ResolvedSchema resolvedSchema = ModelConverters.getInstance() + .resolveAsResolvedSchema( + new AnnotatedType(className).resolveAsRef(false)); + return resolvedSchema.schema.addProperties("email", new StringSchema().description(description)); +} +---- + +=== Customizing swagger static resources + +You can customize swagger documentation static resources located in `META-INF/resources/webjars/swagger-ui/{swagger.version}/`. The list of resources includes: + +- `index.html` +- `swagger-ui-bundle.js` +- `swagger-ui.css` +- `swagger-ui-standalone-preset.js` +- `swagger-ui.css.map` +- `swagger-ui-bundle.js.map` +- `swagger-ui-standalone-preset.js.map` +- `favicon-32x32.png` + +To do this, you need to extend the implementation of `SwaggerIndexPageTransformer` + +[source,java] +---- +public class SwaggerCodeBlockTransformer + extends SwaggerIndexPageTransformer { + // < constructor > + @Override + public Resource transform(HttpServletRequest request, + Resource resource, + ResourceTransformerChain transformer) + throws IOException { + if (resource.toString().contains("swagger-ui.css")) { + final InputStream is = resource.getInputStream(); + final InputStreamReader isr = new InputStreamReader(is); + try (BufferedReader br = new BufferedReader(isr)) { + final String css = br.lines().collect(Collectors.joining()); + final byte[] transformedContent = css.replace("old", "new").getBytes(); + return new TransformedResource(resource, transformedContent); + } // AutoCloseable br > isr > is + } + return super.transform(request, resource, transformer); + } + +} +---- + +Next, add transformer `@Bean` to your `@Configuration` + +[source,java] +---- +@Configuration +public class OpenApiConfig { + @Bean + public SwaggerIndexTransformer swaggerIndexTransformer( + SwaggerUiConfigProperties a, + SwaggerUiOAuthProperties b, + SwaggerUiConfigParameters c, + SwaggerWelcomeCommon d) { + return new SwaggerCodeBlockTransformer(a, b, c, d); + } +} +---- + +Illustrative example + +image::img/static_content_transformation.png[Illustrative example] + +=== Is GraalVM supported ? +The native support available added in spring-boot 3. +If you have some time, do not hesitate to test it before the next release. + +For the OpenAPI REST endpoints, you just need to build your application with the spring `native` profile. + +If you give `@OpenAPIDefinition` or `@SecurityScheme` to a class that has no implementation, that class will disappear when you natively compile. +To avoid this, give the class a `@Configuration`. +---- +@Configuration +@OpenAPIDefinition(info = @Info(title = "My App", description = "description")) +public class OpenAPIConfig { +} +---- + +=== How to Integrate Open API 3 with Spring project (not Spring Boot)? +When your application is using spring without (spring-boot), you need to add beans and auto-configuration that are natively provided in spring-boot. + +For example, lets assume you want load the swagger-ui in spring-mvc application: + +* You mainly, need to add the springdoc-openapi module + +[source,xml] +---- + + org.springdoc + springdoc-openapi-starter-webmvc-ui + last.version + +---- + +* If you don't have the spring-boot and spring-boot-autoconfigure dependencies, you need to add them. And pay attention to the compatibility matrix, between you spring.version and spring-boot.version. For example, in this case (spring.version=5.1.12.RELEASE): + +[source,xml] +---- + + org.springframework.boot + spring-boot-autoconfigure + 3.3.3 + +---- + +* Scan for the `springdoc-openapi` 'auto-configuration classes that spring-boot automatically loads for you. +* Depending on your module, you can find them on the file: `spring.factories` of each `springdoc-openapi` module. + +[source,java] +---- +@Configuration +@EnableWebMvc +public class WebConfig implements WebApplicationInitializer { + + @Override + public void onStartup(ServletContext servletContext) { + WebApplicationContext context = getContext(); + servletContext.addListener(new ContextLoaderListener(context)); + ServletRegistration.Dynamic dispatcher = servletContext.addServlet("RestServlet", + new DispatcherServlet(context)); + dispatcher.setLoadOnStartup(1); + dispatcher.addMapping("/*"); + } + + private AnnotationConfigWebApplicationContext getContext() { + AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); + context.register(this.getClass(), + SpringDocConfiguration.class, + SpringDocConfigProperties.class, + SpringDocSpecPropertiesConfiguration.class, + SpringDocWebMvcConfiguration.class, + MultipleOpenApiSupportConfiguration.class, + SwaggerConfig.class, + SwaggerUiConfigProperties.class, + SwaggerUiOAuthProperties.class, + ); + return context; + } +} +---- + +* Depending on your module, you can find them on the file: `org.springframework.boot.autoconfigure.AutoConfiguration.imports` of each `springdoc-openapi` module. +* For groups usage make sure your `GroupedOpenApi` Beans are scanned. +* If additionally, you are using custom `context path`: `/my-servlet-path`. Make sure you declare the following property: +[source,properties] +---- +spring.mvc.servlet.path=/my-servlet-path +---- + +=== What is the compatibility matrix of `springdoc-openapi` with `spring-boot` ? +`springdoc-openapi 3.x` is compatible with `spring-boot 4`. + +In general, **you should only pick the last stable version as per today {springdoc-upcoming-version}.** + +More precisely, this the exhaustive list of spring-boot versions against which `springdoc-openapi` has been built: + +|=== +| Spring Boot Versions | Springdoc OpenAPI Versions +|`4.0.x` | `3.0.x` + +|=== + + +=== Why am i getting an error: `Swagger UI unable to render definition`, when overriding the default spring registered `HttpMessageConverter`? +When overriding the default spring-boot registered `HttpMessageConverter`, you should have `ByteArrayHttpMessageConverter` registered as well to have proper `springdoc-openapi` support. + +[source,java] +---- + converters.add(new ByteArrayHttpMessageConverter()); + converters.add(new MappingJackson2HttpMessageConverter(jacksonBuilder.build())); +---- +NOTE: Order is very important, when registering `HttpMessageConverters`. + +=== Some parameters are not generated in the resulting OpenAPI spec. + +The issue is caused by the changes introduced by link:https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.2-Release-Notes[Spring-Boot 3.2.0, window="_blank"] +in particular for the **Parameter Name Discovery**. +This can be fixed by adding the `-parameters` arg to the Maven Compiler Plugin. + +[source,xml, subs="attributes+"] +---- + + org.apache.maven.plugins + maven-compiler-plugin + + true + + +---- + diff --git a/src/docs/asciidoc/v4/favicon.ico b/src/docs/asciidoc/v4/favicon.ico new file mode 100644 index 0000000..45468e6 Binary files /dev/null and b/src/docs/asciidoc/v4/favicon.ico differ diff --git a/src/docs/asciidoc/v4/features.adoc b/src/docs/asciidoc/v4/features.adoc new file mode 100644 index 0000000..97d19ed --- /dev/null +++ b/src/docs/asciidoc/v4/features.adoc @@ -0,0 +1,194 @@ +[[features]] +== Springdoc-openapi Features + +=== Adding API Information and Security documentation +The library uses spring-boot application auto-configured packages to scan for the following annotations in spring beans: OpenAPIDefinition and Info. +These annotations declare, API Information: Title, version, licence, security, servers, tags, security and externalDocs. +For better performance of documentation generation, declare @OpenAPIDefinition and @SecurityScheme annotations within a spring managed bean. + +=== Error Handling for REST using @ControllerAdvice +To generate documentation automatically, make sure all the methods declare the HTTP Code responses using the annotation: @ResponseStatus + +=== Disabling the `springdoc-openapi` endpoints +In order to disable the `springdoc-openapi` endpoint (/v3/api-docs by default) use the following property: +[source,properties] +---- +# Disabling the /v3/api-docs endpoint +springdoc.api-docs.enabled=false +---- + +=== Disabling the swagger-ui +In order to disable the swagger-ui, use the following property: +[source,properties] +---- +# Disabling the swagger-ui +springdoc.swagger-ui.enabled=false +---- + +=== Swagger-ui configuration +The library supports the swagger-ui official properties: + +* link:https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/[https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/, window="_blank"] + +You need to declare swagger-ui properties as spring-boot properties. +All these properties should be declared with the following prefix: **springdoc.swagger-ui** + +=== Selecting the Rest Controllers to include in the documentation +Additionally, to @Hidden annotation from swagger-annotations, its possible to restrict the generated OpenAPI description using package or path configuration. + +For the list of packages to include, use the following property: +[source,properties] +---- +# Packages to include +springdoc.packagesToScan=com.package1, com.package2 +---- + +For the list of paths to include, use the following property: +[source,properties] +---- +# Paths to include +springdoc.pathsToMatch=/v1, /api/balance/** +---- + +=== Spring-webflux/WebMvc.fn with Functional Endpoints +Since version v1.5.0, a functional DSL has been introduced, thanks to this enhancement in the spring-framework: link:https://github.com/spring-projects/spring-framework/issues/25938[#25938] + +It's an alternative functional API to the `@RouterOperations` annotations. + +This is a sample DSL, to generate OpenAPI description to the webflux/WebMvc.fn REST endpoints: + +[source,java] +---- +@Bean +RouterFunction routes() { + return route().GET("/foo", HANDLER_FUNCTION, ops -> ops + .operationId("hello") + .parameter(parameterBuilder().name("key1").description("My key1 description")) + .parameter(parameterBuilder().name("key2").description("My key2 description")) + .response(responseBuilder().responseCode("200").description("This is normal response description")) + .response(responseBuilder().responseCode("404").description("This is another response description")) + ).build(); +} +---- + +Here is the link for some sample codes: + +- link:https://github.com/springdoc/springdoc-openapi/blob/master/springdoc-openapi-starter-webflux-api/src/test/java/test/org/springdoc/api/app90/HelloRouter.java[HelloRouter] +- link:https://github.com/springdoc/springdoc-openapi/blob/master/springdoc-openapi-starter-webflux-api/src/test/java/test/org/springdoc/api/app90/quotes/QuotesRouter.java[QuotesRouter] +- link:https://github.com/springdoc/springdoc-openapi/blob/master/springdoc-openapi-starter-webflux-api/src/test/java/test/org/springdoc/api/app90/book/BookRouter.java[BookRouter] +- link:https://github.com/springdoc/springdoc-openapi/blob/master/springdoc-openapi-starter-webflux-api/src/test/java/test/org/springdoc/api/app90/employee/EmployeeRouter.java[EmployeeRouter] +- link:https://github.com/springdoc/springdoc-openapi/blob/master/springdoc-openapi-starter-webflux-api/src/test/java/test/org/springdoc/api/app90/position/PositionRouter.java[PositionRouter] + +And the Demo code, using the functional endpoints DSL: + +- link:https://github.com/springdoc/springdoc-openapi-demos/tree/4.x/demo-spring-boot-webflux-functional[Sample webflux application using functional DSL] + +Since version `v1.3.8`, the support of functional endpoints has been added. +Two main annotations have been added for this purpose: `@RouterOperations` and `@RouterOperation`. + +Only REST APIs with the `@RouterOperations` and `@RouterOperation` can be displayed on the swagger-ui. + +* `@RouterOperation`: It can be used alone, if the Router bean contains one single route related to the REST API.. +When using @RouterOperation, its not mandatory to fill the path + +* `@RouterOperation`, can reference directly a spring Bean (beanClass property) and the underlying method (beanMethod property): Springdoc-openapi, will then inspect this method and the swagger annotations on this method level. + +[source,java] +---- +@Bean +@RouterOperation(beanClass = EmployeeService.class, beanMethod = "findAllEmployees") +RouterFunction getAllEmployeesRoute() { + return route(GET("/employees").and(accept(MediaType.APPLICATION_JSON)), + req -> ok().body( + employeeService().findAllEmployees(), Employee.class)); +} +---- + +* `@RouterOperation`, contains the `@Operation` annotation. +The `@Operation` annotation can also be placed on the bean method level if the property beanMethod is declared. + +IMPORTANT: Don't forget to set **operationId** which is **mandatory**. + +[source,java] +---- +@Bean +@RouterOperation(operation = @Operation(operationId = "findEmployeeById", summary = "Find purchase order by ID", tags = { "MyEmployee" }, + parameters = { @Parameter(in = ParameterIn.PATH, name = "id", description = "Employee Id") }, + responses = { @ApiResponse(responseCode = "200", description = "successful operation", content = @Content(schema = @Schema(implementation = Employee.class))), + @ApiResponse(responseCode = "400", description = "Invalid Employee ID supplied"), + @ApiResponse(responseCode = "404", description = "Employee not found") })) +RouterFunction getEmployeeByIdRoute() { + return route(GET("/employees/{id}"), + req -> ok().body( + employeeRepository().findEmployeeById(req.pathVariable("id")), Employee.class)); +} +---- + +* `@RouterOperations`: This annotation should be used if the Router bean contains multiple routes. +When using RouterOperations, its mandatory to fill the path property. + +* A `@RouterOperations`, contains many `@RouterOperation`. + +[source,java] +---- +@RouterOperations({ @RouterOperation(path = "/getAllPersons", beanClass = PersonService.class, beanMethod = "getAll"), + @RouterOperation(path = "/getPerson/{id}", beanClass = PersonService.class, beanMethod = "getById"), + @RouterOperation(path = "/createPerson", beanClass = PersonService.class, beanMethod = "save"), + @RouterOperation(path = "/deletePerson/{id}", beanClass = PersonService.class, beanMethod = "delete") }) +@Bean +public RouterFunction personRoute(PersonHandler handler) { + return RouterFunctions + .route(GET("/getAllPersons").and(accept(MediaType.APPLICATION_JSON)), handler::findAll) + .andRoute(GET("/getPerson/{id}").and(accept(MediaType.APPLICATION_STREAM_JSON)), handler::findById) + .andRoute(POST("/createPerson").and(accept(MediaType.APPLICATION_JSON)), handler::save) + .andRoute(DELETE("/deletePerson/{id}").and(accept(MediaType.APPLICATION_JSON)), handler::delete); +} +---- + +All the documentations filled using @RouterOperation, might be completed by the router function data. +For that, `@RouterOperation` fields must help identify uniquely the concerned route. +`springdoc-openpi` scans for a unique route related to a `@RouterOperation` annotation, using on the following criteria: + +* by path +* by path and RequestMethod +* by path and produces +* by path and consumes +* by path and RequestMethod and produces +* by path and RequestMethod and consumes +* by path and produces and consumes +* by path and RequestMethod and produces and consumes + +Some code samples are available on GITHUB of demos: + +* link:https://github.com/springdoc/springdoc-openapi-demos/tree/4.x/demo-spring-boot-webflux-functional[Sample application with Functional Endpoints documentation, window="_blank"] + +And some project tests: (from app69 to app75) + +* link:https://github.com/springdoc/springdoc-openapi/tree/master/springdoc-openapi-starter-webflux-api/src/test/java/test/org/springdoc/api[Sample code with Functional Endpoints documentation, window="_blank"] + +=== Integration with WildFly + +* For WildFly users, you need to add the following dependency to make the swagger-ui work: + +[source,xml] +---- + + org.webjars + webjars-locator-jboss-vfs + 0.1.0 + +---- + +++++ + + + +++++ \ No newline at end of file diff --git a/src/docs/asciidoc/v4/getting-started.adoc b/src/docs/asciidoc/v4/getting-started.adoc new file mode 100644 index 0000000..08fcd18 --- /dev/null +++ b/src/docs/asciidoc/v4/getting-started.adoc @@ -0,0 +1,46 @@ +[[getting-started]] +== Getting Started + +For the integration between spring-boot and swagger-ui, add the library to the list of your project dependencies (No additional configuration is needed) + +[source,xml, subs="attributes+"] +---- + + org.springdoc + springdoc-openapi-starter-webmvc-ui + {springdoc-upcoming-version} + +---- + + +This will automatically deploy swagger-ui to a spring-boot application: + +* Documentation will be available in HTML format, using the official link:https://github.com/swagger-api/swagger-ui.git[swagger-ui jars, window="_blank"] +* The Swagger UI page will then be available at `\http://server:port/context-path/swagger-ui.html` and the OpenAPI description will be available at the following url for json format: `\http://server:port/context-path/v3/api-docs` +** server: The server name or IP +** port: The server port +** context-path: The context path of the application +* Documentation will be available in yaml format as well, on the following path : /v3/api-docs.yaml + +TIP: For custom path of the swagger documentation in HTML format, add a custom springdoc property, in your spring-boot configuration file: . + + +[source,properties] +---- +# swagger-ui custom path +springdoc.swagger-ui.path=/swagger-ui.html +---- + +++++ + + + +++++ \ No newline at end of file diff --git a/src/docs/asciidoc/v4/index.adoc b/src/docs/asciidoc/v4/index.adoc new file mode 100644 index 0000000..eb001e3 --- /dev/null +++ b/src/docs/asciidoc/v4/index.adoc @@ -0,0 +1,51 @@ += springdoc-openapi v{springdoc-upcoming-version} +include::_attributes.adoc[] + +`springdoc-openapi` is on link:https://opencollective.com/springdoc[Open Collective, window="_blank"]. If you ❤️ this project consider becoming a link:https://github.com/sponsors/springdoc[sponsor, window="_blank"]. + +This project is sponsored by +++++ +

      + + +    + + + + + + + + + + + + +

      +++++ + +link:https://github.com/springdoc/springdoc-openapi[View project on GitHub, window="_blank"] image:img/github-logo.png[link="https://github.com/springdoc/springdoc-openapi"] + +include::v4/intro.adoc[] + +include::v4/getting-started.adoc[] + +include::v4/modules.adoc[] + +include::v4/features.adoc[] + +include::v4/properties.adoc[] + +include::v4/plugins.adoc[] + +include::v4/demos.adoc[] + +include::v4/migrating-from-springfox.adoc[] + +include::v4/other-resources.adoc[] + +include::v4/sponsor.adoc[] + +include::v4/thanks.adoc[] + +include::v4/faq.adoc[] diff --git a/src/docs/asciidoc/v4/intro.adoc b/src/docs/asciidoc/v4/intro.adoc new file mode 100644 index 0000000..5ee3ee7 --- /dev/null +++ b/src/docs/asciidoc/v4/intro.adoc @@ -0,0 +1,28 @@ +[[Introduction]] +== Introduction + + +`springdoc-openapi` java library helps to automate the generation of API documentation using spring boot projects. +`springdoc-openapi` works by examining an application at runtime to infer API semantics based on spring configurations, class structure and various annotations. + +Automatically generates documentation in JSON/YAML and HTML format APIs. +This documentation can be completed by comments using swagger-api annotations. + +This library supports: + +* OpenAPI 3 +* Spring-boot v4 (Java 17 & Jakarta EE 9) +* JSR-303, specifically for @NotNull, @Min, @Max, and @Size. +* Swagger-ui +* OAuth 2 +* GraalVM native images + +The following video introduces the Library: + + +[link=https://youtu.be/ondlnm5ZoFM?t=9,window=_blank] +image::img/spring-io-24.png[spring.io conference] + + +This is a community-based project, not maintained by the Spring Framework Contributors (Pivotal). + diff --git a/src/docs/asciidoc/v4/migrating-from-springdoc-v1.adoc b/src/docs/asciidoc/v4/migrating-from-springdoc-v1.adoc new file mode 100644 index 0000000..aadf7f8 --- /dev/null +++ b/src/docs/asciidoc/v4/migrating-from-springdoc-v1.adoc @@ -0,0 +1,57 @@ +[[migrating-from-springdoc-v1]] +== Migrating from springdoc-openapi v1 + +All the modules have been renamed. +`springdoc-openapi-starter-common` integrates many spring modules support in order to hide the maximum of complexity. +It allows the support out of the box for `Actuator` / `Spring Cloud Function` / `Spring Data Rest`/ `Spring Native`/ `Spring Hateoas` / `Spring Securtiy` / `Kotlin`/ `Javadoc`. + +The following table describes the main modules changes: + +|=== +|springdoc-openapi-v1 | springdoc-openapi-v2 | Description + +|`springdoc-openapi-common` |`springdoc-openapi-starter-common` | Includes foundation `springdoc-openapi` features +|`springdoc-openapi-data-rest` | `springdoc-openapi-starter-common` | For Spring Data Rest support +|`springdoc-openapi-groovy` | `springdoc-openapi-starter-common` | For Groovy support +|`springdoc-openapi-hateoas` | `springdoc-openapi-starter-common` | For Spring Hateoas support +|`springdoc-openapi-javadoc` | `springdoc-openapi-starter-common` | For Javadoc support +|`springdoc-openapi-kotlin`| `springdoc-openapi-starter-common` | For Kotlin support +|`springdoc-openapi-security` | `springdoc-openapi-starter-common` | For Spring Security support +|`springdoc-openapi-webmvc-core`| `springdoc-openapi-starter-webmvc-api` | For Spring WebMvc support +|`springdoc-openapi-webflux-core` | `springdoc-openapi-starter-webflux-api` | For Spring WebFlux support +|`springdoc-openapi-ui` | `springdoc-openapi-starter-webmvc-ui` | For using the Swagger-UI in a Spring WebMvc context +|`springdoc-openapi-webflux-ui` | `springdoc-openapi-starter-webflux-ui` | For using the Swagger-UI in a Spring WebFlux context +|=== + +IMPORTANT: classes/annotations changes + +|=== +|springdoc-openapi-v1 | springdoc-openapi-v2 + +|`org.springdoc.core.SpringDocUtils` | `org.springdoc.core.utils.SpringDocUtils` +|`org.springdoc.api.annotations.ParameterObject` | `org.springdoc.core.annotations.ParameterObject` +|`org.springdoc.core.GroupedOpenApi` | `org.springdoc.core.models.GroupedOpenApi` +|`org.springdoc.core.customizers.OpenApiCustomiser` | `org.springdoc.core.customizers.OpenApiCustomizer` +|`org.springdoc.core.Constants` | `org.springdoc.core.utils.Constants` +|`org.springdoc.core.SwaggerUiConfigParameters` | `org.springdoc.core.properties.SwaggerUiConfigParameters` +|=== + +TIP: Migration tips + +The following modules are not anymore needed and can be removed: + +- `springdoc-openapi-javadoc` +- `springdoc-openapi-kotlin` +- `springdoc-openapi-data-rest` +- `springdoc-openapi-security` +- `springdoc-openapi-webmvc-core` +- `springdoc-openapi-webflux-core` +- `springdoc-openapi-hateoas` +- `springdoc-openapi-groovy` + +In addition: + +* Replace `springdoc-openapi-ui` by `springdoc-openapi-starter-webmvc-ui` +* Replace `springdoc-openapi-webflux-ui` by `springdoc-openapi-starter-webflux-ui` + + diff --git a/src/docs/asciidoc/v4/migrating-from-springfox.adoc b/src/docs/asciidoc/v4/migrating-from-springfox.adoc new file mode 100644 index 0000000..a4c67ca --- /dev/null +++ b/src/docs/asciidoc/v4/migrating-from-springfox.adoc @@ -0,0 +1,113 @@ +[[migrating-from-springfox]] +== Migrating from SpringFox + +* Remove springfox and swagger 2 dependencies. Add `springdoc-openapi-starter-webmvc-ui` dependency instead. + +[source,xml, subs="attributes+"] +---- + + org.springdoc + springdoc-openapi-starter-webmvc-ui + {springdoc-upcoming-version} + +---- + +* Replace swagger 2 annotations with swagger 3 annotations (it is already included with `springdoc-openapi-starter-webmvc-ui` dependency). +Package for swagger 3 annotations is `io.swagger.v3.oas.annotations`. + +- `@Api` -> `@Tag` +- `@ApiIgnore` -> `@Parameter(hidden = true)` or `@Operation(hidden = true)` or `@Hidden` +- `@ApiImplicitParam` -> `@Parameter` +- `@ApiImplicitParams` -> `@Parameters` +- `@ApiModel` -> `@Schema` +- `@ApiModelProperty(allowEmptyValue = true)` -> `@Schema(nullable = true)` +- `@ApiModelProperty` -> `@Schema` +- `@ApiOperation(value = "foo", notes = "bar")` -> `@Operation(summary = "foo", description = "bar")` +- `@ApiParam` -> `@Parameter` +- `@ApiResponse(code = 404, message = "foo")` -> `@ApiResponse(responseCode = "404", description = "foo")` + +* This step is optional: Only if you have **multiple** `Docket` beans replace them with `GroupedOpenApi` beans. + +Before: + +[source,java, subs="attributes+"] +---- + @Bean + public Docket publicApi() { + return new Docket(DocumentationType.SWAGGER_2) + .select() + .apis(RequestHandlerSelectors.basePackage("org.github.springshop.web.public")) + .paths(PathSelectors.regex("/public.*")) + .build() + .groupName("springshop-public") + .apiInfo(apiInfo()); + } + + @Bean + public Docket adminApi() { + return new Docket(DocumentationType.SWAGGER_2) + .select() + .apis(RequestHandlerSelectors.basePackage("org.github.springshop.web.admin")) + .paths(PathSelectors.regex("/admin.*")) + .apis(RequestHandlerSelectors.withMethodAnnotation(Admin.class)) + .build() + .groupName("springshop-admin") + .apiInfo(apiInfo()); + } +---- + +Now: + +[source,java, subs="attributes+"] +---- + @Bean + public GroupedOpenApi publicApi() { + return GroupedOpenApi.builder() + .group("springshop-public") + .pathsToMatch("/public/**") + .build(); + } + @Bean + public GroupedOpenApi adminApi() { + return GroupedOpenApi.builder() + .group("springshop-admin") + .pathsToMatch("/admin/**") + .addOpenApiMethodFilter(method -> method.isAnnotationPresent(Admin.class)) + .build(); + } +---- + +If you have **only one** `Docket` -- remove it and instead add properties to your `application.properties`: + +[source,properties, subs="attributes+"] +---- +springdoc.packagesToScan=package1, package2 +springdoc.pathsToMatch=/v1, /api/balance/** +---- + +* Add bean of `OpenAPI` type. See example: + +[source,java, subs="attributes+"] +---- + @Bean + public OpenAPI springShopOpenAPI() { + return new OpenAPI() + .info(new Info().title("SpringShop API") + .description("Spring shop sample application") + .version("v0.0.1") + .license(new License().name("Apache 2.0").url("http://springdoc.org"))) + .externalDocs(new ExternalDocumentation() + .description("SpringShop Wiki Documentation") + .url("https://springshop.wiki.github.org/docs")); + } +---- + +* If the swagger-ui is served behind a proxy: + ** link:index.html#how-can-i-deploy-springdoc-openapi-starter-webmvc-ui-behind-a-reverse-proxy[how-can-i-deploy-springdoc-openapi-starter-webmvc-ui-behind-a-reverse-proxy] +* To customise the Swagger UI + ** link:index.html#how-can-i-configure-swagger-ui[how-can-i-configure-swagger-ui] +* To hide an operation or a controller from documentation + ** link:index.html#how-can-i-hide-an-operation-or-a-controller-from-documentation[how-can-i-hide-an-operation-or-a-controller-from-documentation] + + + diff --git a/src/docs/asciidoc/v4/modules.adoc b/src/docs/asciidoc/v4/modules.adoc new file mode 100644 index 0000000..30bd258 --- /dev/null +++ b/src/docs/asciidoc/v4/modules.adoc @@ -0,0 +1,308 @@ +[[modules]] +== Springdoc-openapi Modules + +=== General overview +image::img/common.png[Architecture] + +=== Spring WebMvc support + +* Documentation will be available at the following url for json format: `\http://server:port/context-path/v3/api-docs` +** server: The server name or IP +** port: The server port +** context-path: The context path of the application +* Documentation will be available in yaml format as well, on the following path : /v3/api-docs.yaml +* Add the library to the list of your project dependencies. (No additional configuration is needed) + +[source,xml, subs="attributes+"] +---- + + org.springdoc + springdoc-openapi-starter-webmvc-api + {springdoc-upcoming-version} + +---- + +NOTE: This dependency is relevant if you want to generate the OpenAPI description without using the swagger-ui. + +TIP: For custom path of the OpenAPI documentation in Json format, add a custom springdoc property, in your spring-boot configuration file: + +[source,properties, subs="attributes+"] +---- +# /api-docs endpoint custom path +springdoc.api-docs.path=/api-docs +---- + + +=== Spring WebFlux support + +* Documentation will be available in yaml format as well, on the following path : /v3/api-docs.yaml +* Add the library to the list of your project dependencies (No additional configuration is needed) + +[source,xml, subs="attributes+"] +---- + + org.springdoc + springdoc-openapi-starter-webflux-api + {springdoc-upcoming-version} + +---- + + +=== Spring Hateoas support +The support for Spring Hateoas is available using the dependency springdoc-openapi-hateoas. + +The projects that use `spring-boot-starter-hateoas` should use: + +- `springdoc-openapi-starter-webmvc-api` if they need only the access to the OpenAPI endpoints +- OR `springdoc-openapi-starter-webmvc-ui`, if they need also the access to the swagger-ui + + +=== Spring Data Rest support + +`springdoc-openapi` project supports `spring-boot-starter-data-rest` types like: `@RepositoryRestResource` and `QuerydslPredicate` annotations. + +The projects that use `spring-boot-starter-data-rest` should use: + +- `springdoc-openapi-starter-webmvc-api` if they need only the access to the OpenAPI endpoints +- OR `springdoc-openapi-starter-webmvc-ui`, if they need also the access to the swagger-ui + +=== Spring Security support + +`springdoc-openapi` helps ignoring @AuthenticationPrincipal type in case it is used on REST Controllers. + +`springdoc-openapi` supports also exposing Oauth2 endpoints of `spring-security-oauth2-authorization-server`. + +The projects that use `spring-boot-starter-security` or `spring-security-oauth2-authorization-server` should use: + +- `springdoc-openapi-starter-webmvc-api` if they depend on `spring-boot-starter-web` and they only need the access to the OpenAPI endpoints. +- OR `springdoc-openapi-starter-webmvc-ui`, if they depend on `spring-boot-starter-web` and they also need the access to the swagger-ui. +- OR `springdoc-openapi-starter-webflux-api` if they depend on `spring-boot-starter-webflux` and they only the access to the OpenAPI endpoints. +- OR `springdoc-openapi-starter-webflux-ui`, if they depend on `spring-boot-starter-webflux` and they also need the access to the swagger-ui. + +=== Actuator support + +* In order to display `spring-boot-actuator` endpoints, simply add the following property: + +[source,properties] +---- +springdoc.show-actuator=true +---- + +Starting from the release `1.5.1`, it will be possible to expose the **swagger-ui** and the **openapi** endpoints on **actuator port**. + +NOTE: The actuator management port has to be different from the application port. + +To expose the swagger-ui, on the management port, you should set + +[source,properties] +---- +springdoc.use-management-port=true +# This property enables the openapi and swagger-ui endpoints to be exposed beneath the actuator base path. +management.endpoints.web.exposure.include=openapi, swagger-ui +---- + +Once enabled, you should also be able to see the springdoc-openapi endpoints under: (host and port depends on your settings) +- `\http://serverName:managementPort/actuator` + +For example, if you have the following settings: + +Two endpoints will be available: + +. REST API that holdes the OpenAPI definition: + +- `\http://serverName:managementPort/actuator/openapi` + +. An Endpoint, that routes to the swagger-ui: + +- `\http://serverName:managementPort/actuator/swagger-ui` + +[source,properties] +---- +management.server.port=9090 +---- + +For the example, you should also be able to see the springdoc-openapi endpoints: + +- `\http://serverName:9090/actuator` +- `\http://serverName:9090/actuator/swagger-ui` +- `\http://serverName:9090/actuator/openapi` + +All the path `springdoc-openapi` properties are not applicable when `springdoc.use-management-port=true`. + +TIP: If you want to reach the application endpoints, from the swagger-ui deployed beneath the actuator base path, using a different port from your application, `CORS for your endpoints` on your application level should be enabled. + +Additionally, it is also possible to combine this property, with the existing property to display the actuator endpoints in the swagger-ui. + +[source,properties] +---- +springdoc.show-actuator=true +---- + +Once enabled: +- A dedicated group for the actuator endpoints will be by default added. +- If no group is defined for the application, a default one will be added. + +The swagger-ui will be then accessible through the actuator port: + +- `\http://serverName:managementPort/actuator/swagger-ui` + +If the management port is different from the application port and `springdoc.use-management-port` is not defined but `springdoc.show-actuator` is set to true: + +- The swagger-ui will be then accessible through the application port. For example: `\http://serverName:applicationPort/swagger-ui.html` +- A dedicated group for the actuator endpoints will be by default added. +- If no group is defined for the application, a default one will be added. + + +TIP: If you want to reach the actuator endpoints for this case (different port from your application), `CORS` for your actuator endpoints should be enabled. + +Note: The naming of these new endpoints beneath the actuator base path cannot be customized for now. + +=== Spring Cloud Function Web support + +`spring-cloud-function-web` exposes Java Function as REST endpoint automatically. +* Since version `v1.6.3`, the support of functional endpoints has been added. + +* These starters will display the OpenAPI description of the `spring-cloud-function-web` endpoints. +- If you are using `spring-web`, simply add the `springdoc-openapi-starter-webmvc-ui` dependency. +- If you are using `spring-webflux`, simply add the `springdoc-openapi-starter-webflux-ui` dependency. + + +The customisation of the output can be achieved programmatically through `OpenApiCustomizer` or with the annotations: `@RouterOperations` and `@RouterOperation`. +For annotation usage, you have: +* `@RouterOperation`: It can be used alone, if the customisation is related to a single REST API. +When using `@RouterOperation`, it's not mandatory to fill the path + +* `@RouterOperation`, contains the `@Operation` annotation. +The `@Operation` annotation can also be placed on the bean method level if the property beanMethod is declared. + +IMPORTANT: Don't forget to set **operationId** which is **mandatory**. + +[source,java] +---- +@Bean +@RouterOperation(operation = @Operation(description = "Say hello", operationId = "hello", tags = "persons", + responses = @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = PersonDTO.class))))) +public Supplier helloSupplier() { + return () -> new PersonDTO(); +} +---- + +* `@RouterOperations`: This annotation should be used to describe the multiple REST APIs exposed by `spring-cloud-function-web`. +When using `RouterOperations`, it's mandatory to fill the method property. + +* A `@RouterOperations`, contains many `@RouterOperation`. + +[source,java] +---- +@Bean +@RouterOperations({ + @RouterOperation(method = RequestMethod.GET, operation = @Operation(description = "Say hello GET", operationId = "lowercaseGET", tags = "persons")), + @RouterOperation(method = RequestMethod.POST, operation = @Operation(description = "Say hello POST", operationId = "lowercasePOST", tags = "positions")) +}) +public Function, Flux> lowercase() { + return flux -> flux.map(value -> value.toLowerCase()); +} +---- + +Some code samples are available on GITHUB of demos: + +* link:https://github.com/springdoc/springdoc-openapi-demos/tree/4.x/demo-spring-cloud-function[Sample applications with Spring Cloud Function Web, window="_blank"] + + +=== Kotlin support + +`springdoc-openapi` supports Kotlin types. + +The projects that use `Kotlin` should use: + +- `springdoc-openapi-starter-webmvc-api` if they depend on `spring-boot-starter-web` and they only need the access to the OpenAPI endpoints. +- OR `springdoc-openapi-starter-webmvc-ui`, if they depend on `spring-boot-starter-web` and they also need the access to the swagger-ui. +- OR `springdoc-openapi-starter-webflux-api` if they depend on `spring-boot-starter-webflux` and they only the access to the OpenAPI endpoints. +- OR `springdoc-openapi-starter-webflux-ui`, if they depend on `spring-boot-starter-webflux` and they also need the access to the swagger-ui. + +NOTE: In addition, your project should add `jackson-module-kotlin` as well to have the full support of `Kotlin` types: +[source,xml, subs="attributes+"] +---- + + com.fasterxml.jackson.module + jackson-module-kotlin + +---- + +=== Groovy support + +The projects that use `Groovy` should use: + +- `springdoc-openapi-starter-webmvc-api` if they depend on `spring-boot-starter-web` and they only need the access to the OpenAPI endpoints. +- OR `springdoc-openapi-starter-webmvc-ui`, if they depend on `spring-boot-starter-web` and they also need the access to the swagger-ui. +- OR `springdoc-openapi-starter-webflux-api` if they depend on `spring-boot-starter-webflux` and they only the access to the OpenAPI endpoints. +- OR `springdoc-openapi-starter-webflux-ui`, if they depend on `spring-boot-starter-webflux` and they also need the access to the swagger-ui. + + +=== Javadoc support + +`springdoc-openapi` can introspect `Javadoc` annotations and comments: + +- The javadoc comment of a method: is resolved as the `@Operation` description +- ``@return ``: is resolved as the `@Operation` response description +- The javadoc comment of an attribute: is resolved as '@Schema' description for this field. + +The projects that needs `Javadoc` support should use: + +- `springdoc-openapi-starter-webmvc-api` if they depend on `spring-boot-starter-web` and they only need the access to the OpenAPI endpoints. +- OR `springdoc-openapi-starter-webmvc-ui`, if they depend on `spring-boot-starter-web` and they also need the access to the swagger-ui. +- OR `springdoc-openapi-starter-webflux-api` if they depend on `spring-boot-starter-webflux` and they only the access to the OpenAPI endpoints. +- OR `springdoc-openapi-starter-webflux-ui`, if they depend on `spring-boot-starter-webflux` and they also need the access to the swagger-ui. + +NOTE: In addition, your project should add https://github.com/dnault/therapi-runtime-javadoc[`therapi-runtime-javadoc`] to read Javadoc comments at runtime. +Ensure that you add it as well as its annotation processor to your project's dependencies. Otherwise, the Javadoc support will fail silently. + +[source,xml, subs="attributes+"] +---- + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + com.github.therapi + therapi-runtime-javadoc-scribe + 0.15.0 + + + + + + + + + + com.github.therapi + therapi-runtime-javadoc + 0.15.0 + +---- + +TIP: If both a swagger-annotation description and a javadoc comment are present. The value of the swagger-annotation description will be used. + +=== Springdoc-openapi BOM +Starting from version `v2.8.7`, `springdoc-openapi` provides a BOM (Bill of Materials) to manage the dependencies of the project. +You can declare it in your project as follows: + +[source,xml, subs="attributes+"] +---- + + + + org.springdoc + springdoc-openapi-bom + {springdoc-upcoming-version} + pom + import + + + +---- \ No newline at end of file diff --git a/src/docs/asciidoc/v4/other-resources.adoc b/src/docs/asciidoc/v4/other-resources.adoc new file mode 100644 index 0000000..eca3349 --- /dev/null +++ b/src/docs/asciidoc/v4/other-resources.adoc @@ -0,0 +1,27 @@ +[[other-resources]] +== Other resources + +=== Additional resources to get started +- link:https://github.com/springdoc/springdoc-openapi[View project on GitHub, window="_blank"] image:img/github-logo.png[link="https://github.com/springdoc/springdoc-openapi"] +- link:https://prezi.com/view/r4DP4TCmYUJk1eaqjKG4/[Springdoc-openapi presentation, window="_blank"] +- link:https://www.baeldung.com/spring-rest-openapi-documentation[Baeldung, window="_blank"] +- link:https://dzone.com/articles/openapi-3-documentation-with-spring-boot[DZone Part1, window="_blank"] +- link:https://dzone.com/articles/doing-more-with-springdoc-openapi[DZone Part2, window="_blank"] +- link:https://dzone.com/articles/extending-swagger-and-spring-doc-open-api[Extending Swagger and Spring Doc Open API, window="_blank"] +- link:https://piotrminkowski.com/2020/02/20/microservices-api-documentation-with-springdoc-openapi/[Piotrminkowski Blog, window="_blank"] + + +=== Dependencies repository + +The `springdoc-openapi` libraries are hosted on maven central repository. +The artifacts can be viewed accessed at the following locations: + +Releases: + +* link:https://central.sonatype.com/search?q=g:org.springdoc[https://central.sonatype.com/search?q=g:org.springdoc, window="_blank"] + +Snapshots: + +* link:https://central.sonatype.com/service/rest/repository/browse/maven-snapshots/org/springdoc/[https://central.sonatype.com/service/rest/repository/browse/maven-snapshots/org/springdoc/, window="_blank", window="_blank"] + + diff --git a/src/docs/asciidoc/v4/plugins.adoc b/src/docs/asciidoc/v4/plugins.adoc new file mode 100644 index 0000000..aabccf4 --- /dev/null +++ b/src/docs/asciidoc/v4/plugins.adoc @@ -0,0 +1,81 @@ +[[plugins]] +== Springdoc-openapi Plugins + +=== Maven plugin + +The aim of `springdoc-openapi-maven-plugin` is to generate json and yaml OpenAPI description during build time. +The plugin works during integration-tests phase, and generate the OpenAPI description. +The plugin works in conjunction with spring-boot-maven plugin. + +You can test it during the integration tests phase using the maven command: + +[source,bash] +---- +mvn verify +---- + +In order to use this functionality, you need to add the plugin declaration on the plugins section of your pom.xml: + +[source,xml] +---- + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot-maven-plugin.version} + + -Dspring.application.admin.enabled=true + + + + + start + stop + + + + + + org.springdoc + springdoc-openapi-maven-plugin + 1.5 + + + integration-test + + generate + + + + +---- + +For more custom settings of the springdoc-openapi-maven-plugin, you can consult the plugin documentation: + +* link:https://github.com/springdoc/springdoc-openapi-maven-plugin[https://github.com/springdoc/springdoc-openapi-maven-plugin, window="_blank"] + +=== Gradle plugin + +This plugin allows you to generate an OpenAPI 3 specification for a Spring Boot application from a Gradle build. + +[source,groovy] +---- +plugins { + id("org.springframework.boot") version "3.1.2" + id("org.springdoc.openapi-gradle-plugin") version "1.9.0" +} +---- + +When you add this plugin and its runtime dependency plugins to your build file, the plugin creates the following tasks: + +* forkedSpringBootRun +* generateOpenApiDocs + +[source,bash] +---- +gradle clean generateOpenApiDocs +---- + +For more custom configuration of `springdoc-openapi-gradle-plugin` ,you can consult the plugin documentation: + +* link:https://github.com/springdoc/springdoc-openapi-gradle-plugin[https://github.com/springdoc/springdoc-openapi-gradle-plugin, window="_blank"] + diff --git a/src/docs/asciidoc/v4/properties.adoc b/src/docs/asciidoc/v4/properties.adoc new file mode 100644 index 0000000..b0948ba --- /dev/null +++ b/src/docs/asciidoc/v4/properties.adoc @@ -0,0 +1,18 @@ +[[properties]] +== Springdoc-openapi Properties + +`springdoc-openapi` relies on standard link:https://docs.spring.io/spring-boot/reference/features/external-config.html[spring configuration properties, window="_blank"] (yml or properties) using the standard files locations. + + +=== springdoc-openapi core properties + +include::core-properties.adoc[] + +=== swagger-ui properties +- The support of the swagger-ui properties is available on `springdoc-openapi`. See link:https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/[Official documentation, window="_blank"]. + +- You can use the same swagger-ui properties in the documentation as Spring Boot properties. + +NOTE: All these properties should be declared with the following prefix: `springdoc.swagger-ui` + +include::ui-properties.adoc[] diff --git a/src/docs/asciidoc/v4/sponsor.adoc b/src/docs/asciidoc/v4/sponsor.adoc new file mode 100644 index 0000000..ed4bc53 --- /dev/null +++ b/src/docs/asciidoc/v4/sponsor.adoc @@ -0,0 +1,53 @@ +[[sponsor]] +== Sponsor + +`springdoc-openapi` is on link:https://opencollective.com/springdoc[Open Collective, window="_blank"]. + +If you ❤️ this project consider becoming a link:https://github.com/sponsors/springdoc[sponsor, window="_blank"]. + +This money is used to cover project expenses and your donation will help the project live and grow successfully. + +Thank you to our bronze sponsors! +++++ +

      + + +    + + + + + + + + + + + + +

      +++++ + +=== Benefits of being a bronze sponsor +Bronze sponsors donate $50 per month to the project, and get the following benefits: + +- You will receive a Sponsor badge 🎖!. Visibility on the front page of https://springdoc.org in the `welcome` page (about 55,000 views/month on May, 2022). +- “Thank you” tweet from `springdoc team'. + +=== Benefits of being a silver sponsor +Silver sponsors donate $100 per month to the project, and get the following benefits: + +- Same benefits as bronze sponsors (visibility on main pages, and thank you tweet). +- The ability to get support for 2 `issues` every month, non transferable. +- If issues are not created by the end of the month, it is lost + +=== Benefits of being a gold sponsor +Gold sponsors donate $500 per month to the project, and get the following benefits: + +- Same benefits as silver sponsors (visibility on main pages, and thank you tweet). +- The ability to get support for 10 `issues` every month, non transferable. +- Company logos on all https://springdoc.org page footers +- If issues are not created by the end of the month, the remaining ones are lost. + + + diff --git a/src/docs/asciidoc/v4/thanks.adoc b/src/docs/asciidoc/v4/thanks.adoc new file mode 100644 index 0000000..2034eaf --- /dev/null +++ b/src/docs/asciidoc/v4/thanks.adoc @@ -0,0 +1,9 @@ +[[thanks]] +== Special Thanks + +* Thank you to link:https://spring.io/team[The Spring Team , window="_blank"] for sharing all relevant resources around Spring projects. + +* Thanks a lot link:https://www.jetbrains.com/?from=springdoc-openapi[JetBrains, window="_blank"] for supporting springdoc-openapi project. + +image::https://resources.jetbrains.com/storage/products/company/brand/logos/jetbrains.svg[JetBrains logo] + diff --git a/src/docs/asciidoc/v4/ui-properties.adoc b/src/docs/asciidoc/v4/ui-properties.adoc new file mode 100644 index 0000000..ecce440 --- /dev/null +++ b/src/docs/asciidoc/v4/ui-properties.adoc @@ -0,0 +1,66 @@ +[[ui-properties]] + +|=== +|Parameter name | Default Value | Description + +|springdoc.swagger-ui.path | `/swagger-ui.html` |`String`, For custom path of the swagger-ui HTML documentation. +|springdoc.swagger-ui.enabled | `true` | `Boolean`. To disable the swagger-ui endpoint (/swagger-ui.html by default). +|springdoc.swagger-ui.configUrl | `/v3/api-docs/swagger-config` | `String`. URL to fetch external configuration document from. +|springdoc.swagger-ui.layout | `BaseLayout` | `String`. The name of a component available via the plugin system to use as the top-level layout for Swagger UI. +|springdoc.swagger-ui.validatorUrl | | By default, Swagger UI does not validate specs. You can use this parameter to set a validator URL, for example for against swagger.io’s online validator. +|springdoc.swagger-ui.tryItOutEnabled | `false` |`Boolean`. Controls whether the "Try it out" section should be enabled by default. +|springdoc.swagger-ui.filter | `false` | `Boolean OR String`. If set, enables filtering. The top bar will show an edit box that you can use to filter the tagged operations that are shown. Can be Boolean to enable or disable, or a string, in which case filtering will be enabled using that string as the filter expression. Filtering is case sensitive matching the filter expression anywhere inside the tag. +|springdoc.swagger-ui.operationsSorter | | `Function=(a => a)`. Apply a sort to the operation list of each API. It can be 'alpha' (sort by paths alphanumerically), 'method' (sort by HTTP method) or a function (see Array.prototype.sort() to know how sort function works). Default is the order returned by the server unchanged. +|springdoc.swagger-ui.tagsSorter | | `Function=(a => a)`. Apply a sort to the tag list of each API. It can be 'alpha' (sort by paths alphanumerically) or a function link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort[see Array.prototype.sort() , window="_blank"] to learn how to write a sort function). Two tag name strings are passed to the sorter for each pass. Default is the order determined by Swagger UI. +|springdoc.swagger-ui.oauth2RedirectUrl | `/swagger-ui/oauth2-redirect.html` | `String`. OAuth redirect URL. +|springdoc.swagger-ui.displayOperationId | `false` | `Boolean`. Controls the display of operationId in operations list. The default is `false`. +|springdoc.swagger-ui.displayRequestDuration | `false` | `Boolean`. Controls the display of the request duration (in milliseconds) for "Try it out" requests. +|springdoc.swagger-ui.deepLinking | `false` | `Boolean`. If set to `true`, enables deep linking for tags and operations. See the [Deep Linking documentation](https://swagger.io/docs/open-source-tools/swagger-ui/usage/deep-linking) for more information. +|springdoc.swagger-ui.defaultModelsExpandDepth | `1` | `Number`. The default expansion depth for models (set to -1 completely hide the models). +|springdoc.swagger-ui.defaultModelExpandDepth | `1` | `Number`. The default expansion depth for the model on the model-example section. +|springdoc.swagger-ui.defaultModelRendering | | `String=["example"*, "model"]`. Controls how the model is shown when the API is first rendered. (The user can always switch the rendering for a given model by clicking the 'Model' and 'Example Value' links.) +|springdoc.swagger-ui.docExpansion | | `String=["list"*, "full", "none"]`. Controls the default expansion setting for the operations and tags. It can be 'list' (expands only the tags), 'full' (expands the tags and operations) or 'none' (expands nothing). +|springdoc.swagger-ui.maxDisplayedTags | | `Number`. If set, limits the number of tagged operations displayed to at most this many. The default is to show all operations. +|springdoc.swagger-ui.showExtensions | `false` | `Boolean`. Controls the display of vendor extension (`x-`) fields and values for Operations, Parameters, and Schema. +|springdoc.swagger-ui.url | | `String`.To configure, the path of a custom OpenAPI file . Will be ignored if `urls` is used. +|springdoc.swagger-ui.showCommonExtensions | `false` | `Boolean`. Controls the display of extensions (`pattern`, `maxLength`, `minLength`, `maximum`, `minimum`) fields and values for Parameters. +|springdoc.swagger-ui.supportedSubmitMethods | | `Array=[get, put, post, delete, options, head, patch, trace]`. List of HTTP methods that have the "Try it out" feature enabled. An empty array disables "Try it out" for all operations. This does not filter the operations from the display. +|springdoc.swagger-ui.queryConfigEnabled | `false` | `Boolean`. Disabled since `v1.6.0`. This parameter enables (legacy) overriding configuration parameters via URL search params. link:https://github.com/swagger-api/swagger-ui/security/advisories/GHSA-qrmm-w75w-3wpx[See security advisory , window="_blank"] before enabling this feature. +|springdoc.swagger-ui.oauth. additionalQueryStringParams | | `String`. Additional query parameters added to authorizationUrl and tokenUrl. +|springdoc.swagger-ui.disable-swagger-default-url | `false` | `Boolean`. To disable the swagger-ui default petstore url. (Available since v1.4.1). +|springdoc.swagger-ui.urls[0].url | | `URL`. The url of the swagger group, used by Topbar plugin. URLs must be unique among all items in this array, since they're used as identifiers. +|springdoc.swagger-ui.urls[0].name | | `String`. The name of the swagger group, used by Topbar plugin. Names must be unique among all items in this array, since they're used as identifiers. +|springdoc.swagger-ui.urlsPrimaryName | | `String`. The name of the swagger group which will be displayed when Swagger UI loads. +|springdoc.swagger-ui.oauth.clientId | | `String`. Default clientId. MUST be a string. +|springdoc.swagger-ui.oauth.clientSecret | | `String`. Default clientSecret. Never use this parameter in your production environment. It exposes crucial security information. This feature is intended for dev/test environments only. +|springdoc.swagger-ui.oauth.realm | | `String`. realm query parameter (for OAuth 1) added to authorizationUrl and tokenUrl. +|springdoc.swagger-ui.oauth.appName | | `String`. OAuth application name, displayed in authorization popup. +|springdoc.swagger-ui.oauth.scopeSeparator | | `String`. OAuth scope separator for passing scopes, encoded before calling, default value is a space (encoded value %20). +|springdoc.swagger-ui.csrf.enabled | `false` | `Boolean`. To enable CSRF support +|springdoc.swagger-ui.csrf.use-local-storage | `false` | `Boolean`. To get the CSRF token from the Local Storage. +|springdoc.swagger-ui.csrf.use-session-storage | `false` | `Boolean`. To get the CSRF token from the Session Storage. +|springdoc.swagger-ui.csrf.cookie-name | `XSRF-TOKEN` | `String`. Optional CSRF, to set the CSRF cookie name. +|springdoc.swagger-ui.csrf.header-name | `X-XSRF-TOKEN` | `String`. Optional CSRF, to set the CSRF header name. +|springdoc.swagger-ui.syntaxHighlight.activated | `true` | `Boolean`. Whether syntax highlighting should be activated or not. +|springdoc.swagger-ui.syntaxHighlight.theme | `agate` | `String`. `String=["agate"*, "arta", "monokai", "nord", "obsidian", "tomorrow-night"]`. link:https://highlightjs.org/static/demo/[Highlight.js, window="_blank"] syntax coloring theme to use. (Only these 6 styles are available.) +|springdoc.swagger-ui.oauth. useBasicAuthentication WithAccessCodeGrant | `false` | `Boolean`. Only activated for the accessCode flow. During the authorization_code request to the tokenUrl, pass the Client Password using the HTTP Basic Authentication scheme (Authorization header with Basic base64encode(client_id + client_secret)). +|springdoc.swagger-ui.oauth. usePkceWithAuthorization CodeGrant | `false` | `Boolean`.Only applies to authorizatonCode flows. Proof Key for Code Exchange brings enhanced security for OAuth public clients. +|springdoc.swagger-ui.persistAuthorization | `false` | `Boolean`. If set to true, it persists authorization data and it would not be lost on browser close/refresh +|springdoc.swagger-ui.use-root-path | `false` | `Boolean`. If set to true, the swagger-ui will be accessible from the application root path directly. + +|=== + +++++ + + + +++++ +