{"id":19795400,"url":"https://github.com/itemconsulting/xp-codegen-plugin","last_synced_at":"2025-05-01T03:30:28.172Z","repository":{"id":37433612,"uuid":"241078790","full_name":"ItemConsulting/xp-codegen-plugin","owner":"ItemConsulting","description":"Gradle plugin that generates TypeScript-interfaces or JSDoc for Enonic","archived":false,"fork":false,"pushed_at":"2025-03-28T15:16:55.000Z","size":348,"stargazers_count":6,"open_issues_count":8,"forks_count":0,"subscribers_count":12,"default_branch":"main","last_synced_at":"2025-04-06T08:06:59.951Z","etag":null,"topics":["codegeneration","enonic","gradle-plugin","typescript"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ItemConsulting.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-02-17T10:23:43.000Z","updated_at":"2025-03-28T15:16:58.000Z","dependencies_parsed_at":"2024-03-27T10:28:58.737Z","dependency_job_id":"75894b09-ada0-460d-a6ad-0602199d8241","html_url":"https://github.com/ItemConsulting/xp-codegen-plugin","commit_stats":null,"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ItemConsulting%2Fxp-codegen-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ItemConsulting%2Fxp-codegen-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ItemConsulting%2Fxp-codegen-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ItemConsulting%2Fxp-codegen-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ItemConsulting","download_url":"https://codeload.github.com/ItemConsulting/xp-codegen-plugin/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251817808,"owners_count":21648811,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["codegeneration","enonic","gradle-plugin","typescript"],"created_at":"2024-11-12T07:16:16.298Z","updated_at":"2025-05-01T03:30:28.163Z","avatar_url":"https://github.com/ItemConsulting.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Enonic XP Codegen plugin\n\n![build-test](https://github.com/ItemConsulting/xp-codegen-plugin/workflows/build-test/badge.svg?branch=main) [![PluginVersion](https://img.shields.io/maven-metadata/v.svg?label=gradle\u0026metadataUrl=https://plugins.gradle.org/m2/no/item/xp/codegen/no.item.xp.codegen.gradle.plugin/maven-metadata.xml)](https://plugins.gradle.org/plugin/no.item.xp.codegen)\n\nThis is Gradle plugin for *Enonic XP 7 projects*. It requires at least **Gradle 8.7**.\n\nThe plugin parses the Enonic projects XML-files, and generates **TypeScript interfaces** that can be used in your \nserver- or client-side code.\n\nThis creates a **tight coupling** between your configuration and your code. If you change an xml-file, the TypeScript\n-files will be regenerated, and it will not compile until you have fixed your code.\n\nThis plugin can create interfaces for:\n\n - Content types\n - Pages\n - Parts\n - Site\n - Layout\n - Tasks\n - Macros\n - Id-provider\n - Mixins\n - X-data\n\nThe pluging includes in addition a feature to check that the xml elements marked with the attribute \"i18n\" have been translated in the file \\src\\main\\resources\\i18n\\phrases.properties. Any element marked with \"i18n\" missing in the phrases.properties will be written in a temporory file in the same directory as phrases.properties named phrases.tmp.properties. The purpose is to make it easy for you to copy and paste entries from phrases.tmp.properties to phrases.properties and translate them. This feature is implemented as a gradle task called \"checkTranslation\" that is built-in this plugin.\n \n ## Usage\n\nTo get started add the following to your project's *build.gradle* file:  \n \n ```groovy\nplugins {\n    id 'java'\n    id 'no.item.xp.codegen' version '2.7.0'\n}\n\njar {\n    // Add this before your TypeScript build task\n    dependsOn += generateTypeScript\n}\n\n// Add dependency to webpack tasks too\ntask serverWebpack( type: NodeTask, dependsOn: [ npmInstall, generateTypeScript ] ) {\n  ...\n}\n ```\n\n## Update *./tsconfig.json*\n\nBy setting the `rootDirs` field in *tsconfig.json*, you can \"overlay\" the two directory structures over each other, and\nreferences to generated Types becomes very natural.\n\nE.g if you have a content type in \n\"**./resources/site/content-types/article/article.xml**\", the generated TypeScript interface for that type can be imported\nfrom \"**./resources/site/content-types/article**\" (or alternatively from \"**./resources/site/content-types**\").\n\n\n```json\n{\n  \"compilerOptions\": {\n    ...\n      \n    \"rootDirs\": [\n      \"./src/main/resources\",\n      \"./.xp-codegen\"\n    ]\n  },\n  \"include\": [\n    \"./.xp-codegen/**/*\",\n    \"./src/main/resources/**/*\"\n  ]\n}\n```\n\n## Examples\n\n### Generating TypeScript interfaces\n\nHere is an example of how an xml-file can be parsed to create a TypeScript interface.\n\nWe have created a content type for `Article` in the file **content-types/article/article.xml**:\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003ccontent-type\u003e\n  \u003cdisplay-name\u003eArticle\u003c/display-name\u003e\n  \u003csuper-type\u003ebase:structured\u003c/super-type\u003e\n  \u003cform\u003e\n    \u003cinput name=\"title\" type=\"TextLine\"\u003e\n      \u003clabel\u003eTitle of the article\u003c/label\u003e\n      \u003coccurrences minimum=\"1\" maximum=\"1\"/\u003e\n    \u003c/input\u003e\n\n    \u003cinput name=\"body\" type=\"HtmlArea\"\u003e\n      \u003clabel\u003eMain text body\u003c/label\u003e\n      \u003coccurrences minimum=\"0\" maximum=\"1\"/\u003e\n    \u003c/input\u003e\n  \u003c/form\u003e\n\u003c/content-type\u003e\n```\n\nWe can then run the `./gradlew generateTypeScript` task, which will generate a new file in \n**content-types/article/article.ts** with the following content:\n\n```typescript\n// WARNING: This file was automatically generated by \"no.item.xp.codegen\". You may lose your changes if you edit it.\nexport interface Article {\n  /** \n   * Title of the article\n   */\n  title: string;\n \n  /**\n   * Main text body \n   */\n  body?: string;\n}\n```\n\n### Configuration options\n\nThe following configuration options can be used:\n \n  * *singleQuote* (`boolean`) – If `true` all `\"` in output will be replaced with `'`.\n  * *prependText* (`string`) – Code to prepend to all the generated code files. By default this is the WARNING-text.\n\n```groovy\njar {\n    dependsOn += generateTypeScript {\n      singleQuote = true\n      prependText = \"// This is a different message\"\n    }\n}\n```\n\n\u003e **Note**\n\u003e You can use `prependText` to give instructions to the e.g. the linter. If you add\n`/* eslint-disable prettier/prettier */` you can stop [eslint](https://eslint.org/) from processing the generated files.\n\n### Using the generated interfaces\n\nHere we can see an example of using generated interfaces it in a part specified in \n**\"./site/parts/article-view/article-view.xml\"**.\n\n```typescript\n// We can import the generated Article interface from \"./site/content-types/index.d.ts\"\nimport type { Article } from \"../../content-types\";\n// We can import the shape of the part config from \"./index.d.ts\"\nimport type { ArticleView } from \".\";\n// imports from XP libraries:\nimport { getContent, getComponent } from \"/lib/xp/portal\";\nimport { render } from \"/lib/thymeleaf\";\nimport type { PartComponent } from \"@enonic-types/core\";\n\nconst view = resolve(\"article-view.html\");\n\ntype PartArticleView =  PartComponent\u003c\"com.myproject:article-view\", ArticleView\u003e;\n\nexport function get(): XP.Response {\n  const content = getContent\u003cContent\u003cArticle, \"com.myproject:article\"\u003e\u003e();\n  const part = getComponent\u003cPartArticleView\u003e();\n\n  assertIsDefined(content);\n  assertIsDefined(part);\n  \n  return {\n    status: 200,\n    body: render\u003cThymeleafParams\u003e(view, {\n      title: content.displayName,\n      preface: content.data.preface,\n      backgroundColor: part.config.backgroundColor\n    }),\n  };\n}\n\ninterface ThymeleafParams {\n  title: string;\n  preface: string | undefined;\n  backgroundColor: string;  \n}\n\nfunction assertIsDefined\u003cT\u003e(value: T): asserts value is NonNullable\u003cT\u003e {\n  if (value === undefined || value === null) {\n    throw new Error(`${value} is not defined`);\n  }\n}\n```\n\n### Generating phases to be translated\nWe can then run the `./gradlew checkTranslation` task, it will generate the file \\src\\main\\resources\\i18n\\phrases.tmp.properties which contains the phrases that are missing from the phrases.properties. It is then easy to translate and then copy and past those entries in the phrases.properties. \n\n\n## Development\n\n### Local manual testing\n\nTo test this plugin locally you can run the following task to publish the plugin locally on your machine.\n\n```bash\n./gradlew publishToMavenLocal\n```\n\nThen – in your Enonic-project – you can add the following to the top of your settings.gradle file to use the plugin:\n\n ```groovy\npluginManagement {\n    repositories {\n        mavenLocal()\n        gradlePluginPortal()\n    }\n}\n ```\n\nTo use the plugin your can just run the following task:\n\n```bash\n./gradlew generateTypeScript\n```\n\n### Running tests\n\nTo run the unit tests, linting and plugin verification in the project you can run:\n\n```bash\n./gradlew test\n./gradlew ktlintFormat\n./gradlew validatePlugins\n```\n\nYou should always run `./gradlew ktlintFormat` before committing code to git!\n\n### Publishing to plugin portal\n\nTo publish to the plugin portal, you first need to set up your local api-keys. Instrunctions can be found in the \n[plugin documentation](https://plugins.gradle.org/docs/submit).\n\nThen you can run the following to submit the plugin to the plugin portal:\n\n```bash\n./gradlew publishPlugins\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fitemconsulting%2Fxp-codegen-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fitemconsulting%2Fxp-codegen-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fitemconsulting%2Fxp-codegen-plugin/lists"}