New Gradle plugin for TypeScript and JSDoc code generation

Hi everyone!

I have some great news today!

New Gradle plugin

Last week we released version 1.0.0 of a new open source Gradle plugin (xp-codegen-plugin). :partying_face:

The plugin reads the XML-files in your Enonic project, and outputs TypeScript- or JavaScript-files that describes the shape of json you use in your project. The output can either be TypeScript-interfaces or JSDoc.

Why do I need this?

There are two main benefits to using the generated code in your codebase.

  1. Code completion. Your IDE will be able to suggest what the possible legal values are.
  2. Tight coupling between code and data. If you change an XML-file, the TypeScript or JavaScript-files will be re-generated, and it will cause type errors in your code. Now you can catch the error at compiletime, instead of maybe at runtime.


Here is an example of how an xml-file can be parsed to create a TypeScript interface or JSDoc.

We have created a content type for Article in the file content-types/article/article.xml:

<?xml version="1.0" encoding="UTF-8"?>
    <input name="title" type="TextLine">
      <label>Title of the article</label>
      <occurrences minimum="1" maximum="1"/>

    <input name="body" type="HtmlArea">
      <label>Main text body</label>
      <occurrences minimum="0" maximum="1"/>

We can then run the ./gradlew generateTypeScript task, which will generate a new file in
content-types/article/article.ts with the following content:

export interface Article {
   * Title of the article
  title: string;

   * Main text body
  body?: string;

The Article-interface can be used in your code like this:


We could also have run the ./gradlew generateJSDoc task, which will generate a new file in
content-types/article/article.js with the following content:

 * @typedef {Object} Article
 * @property {string} title Title of the article
 * @property {string} [body] Main text body

How to add the plugin to your project

To get started add the following to your project’s build.gradle file:

plugins {
   id  'no.item.xp.codegen' version '1.0.0'

jar {
   // Add this before your TypeScript build task
   dependsOn += generateTypeScript

   // If you want JSDoc generated instead (because JS-project), use this:
   // dependsOn += generateJSDoc

Wait, didn’t the enonic-ts-codegen npm package do the same thing?

Yes, enonic-ts-codegen did the same thing, but we have deprecated that project in favor of this project.

You can think of the enonic-ts-codegen project a prototype for xp-codegen-plugin. It was used on several big production projects with great success, and most of the output files are exactly the same in both projects.

Why the need for a rewrite in a new language?

We wanted to remove the dependency on npm, which not all XP-projects has support for. Gradle on the other hand is required everywhere. The Gradle plugin also have some performance enhancements. It will use multiple threads, and it uses incremental build, so that only the XML-files that have changed will trigger a re-write of the TS-/JS-files.

Other notable changes in xp-codegen-plugin compared to enonic-ts-codegen includes:

  1. All input types in Enonic XP 7 is now supported!
  2. All types that can be returned as Arrays now has support for that (based on <occurrences ... /> ).
  3. <option-set> is rendered as a tagged union in TypeScript.
  4. Mixins that depend on other mixins are now supported.
  5. The plugin can render JSDoc instead of TypeScript

Have fun!

I hope you will enjoy using this plugin! Generated TypeScript-interfaces has really been a quality of life improvement (and quality of code improvement) in our projects.

Feel free get in touch if you have any questions, comments or feature requests! Some places to find me:

  • Create an issue on Github
  • Send me a DM on the Enonic Community Slack, search for Tom Arild Jakobsen (Item)
  • Just post a comment below.

There are no download statistics for the Gradle plugin, so please star it on Github if you use it, so we can get some sense if there is interest in this at all.