Visit this section to see how to run the editor with AI driven completions using the OpenAI API.
Backend and frontend for a PlantUML editor web application
- The backend generates images from PlantUML using plantuml/plantuml. It also provides annotations in case of invalid source.
- The fully responsive frontend allows you to see the generated images as you type and also highlights syntax errors linewise
PlantUML source for this diagram
@startuml
autonumber
actor Developer
participant PlantUmlEditorFrontend
participant PlantUmlEditorBackend
activate Developer
Developer -> PlantUmlEditorFrontend: type plantuml source
activate PlantUmlEditorFrontend
PlantUmlEditorFrontend -> PlantUmlEditorBackend: get annotations
activate PlantUmlEditorBackend
alt #pink source invalid
PlantUmlEditorBackend --> PlantUmlEditorFrontend: error annotations
PlantUmlEditorFrontend --> Developer: marked error annotation at specific line
else #lightgreen source valid
PlantUmlEditorBackend --> PlantUmlEditorFrontend: empty annotations
deactivate PlantUmlEditorBackend
PlantUmlEditorFrontend -> PlantUmlEditorBackend: generate image for source
activate PlantUmlEditorBackend
PlantUmlEditorBackend -> PlantUmlEditorBackend: generate image using plantuml/plantuml
PlantUmlEditorBackend --> PlantUmlEditorFrontend: generated image
deactivate PlantUmlEditorBackend
PlantUmlEditorFrontend --> Developer: visualized generated image
end
deactivate PlantUmlEditorFrontend
deactivate Developer
@enduml
A running demo is available at https://plantuml.mseiche.de/.
docker run -d -p 80:8080 --name plantuml-editor hakenadu/plantuml-editor
then open the app in your browser: http://localhost
plantuml-editor:
image: hakenadu/plantuml-editor
container_name: plantuml-editor
ports:
- "80:8080"
then open the app in your browser: http://localhost
You may customize parts of the application by providing config options.
The backend is configured using environment variables.
For the app published at https://plantuml.mseiche.de/ I'm using the following frontend-config.json
{
"share": {
"description": "<p>Your PlantUML spec will be stored symmetrically encrypted via <a href=\"https:\/\/en.wikipedia.org\/wiki\/WebDAV\">WebDAV<\/a>.<\/p><p>The information needed to decrypt the stored data is the id which is sent by your browser when accessing the data.<\/p><p class=\"mb-0\">Anyhow if you use this functionality you agree to my <a href=\"https:\/\/mseiche.de\/terms-of-service\">Terms of Service<\/a><\/p>",
"imageOnlyLinks": {
"visible": true,
"warningMessage": "If an image only link is used, the key is inserted as a query parameter for a GET request. The key will therefore most likely appear in my reverse proxy logs when the Link is used to download the image."
}
},
"footer": {
"actions": [
{
"type": "popup",
"icon": {
"type": "material",
"name": "privacy_tip"
},
"content": "<div>This page belongs to <a href=\"https:\/\/mseiche.de\" target=\"_blank\">mseiche.de<\/a> therefore the following documents also apply for this page:<ul class=\"mb-0\"><li><a href=\"https:\/\/mseiche.de\/privacy-policy\" target=\"_blank\">Privacy Policy<\/a><\/li><li><a href=\"https:\/\/mseiche.de\/terms-of-service\" target=\"_blank\">Terms of Service<\/a><\/li><li><a href=\"https:\/\/mseiche.de\/about\" target=\"_blank\">About<\/a><\/li><\/ul><\/div>",
"tooltip": "Privacy and Terms of Service"
},
{
"type": "link",
"icon": {
"type": "img",
"src": "assets/images/github.svg",
"width": "28",
"height": "28"
},
"href": "https://github.com/Hakenadu/plantuml-editor",
"tooltip": "View the code for this page on GitHub"
},
{
"type": "link",
"icon": {
"type": "img",
"src": "assets/images/mseiche.svg",
"width": "28",
"height": "28"
},
"href": "https://mseiche.de",
"tooltip": "Visit my main page"
}
]
}
}
{
"intro": {
"description": "<h1>Hi there</h1><p>This is the content which will be shown if the editor is empty</p>",
"slideshow": {
"showMessage": true,
"visible": true
}
},
"share": {
"description": "<p>Your PlantUML spec will be stored symmetrically encrypted via <a href=\"https:\/\/en.wikipedia.org\/wiki\/WebDAV\">WebDAV<\/a>.<\/p><p>The information needed to decrypt the stored data is the id which is sent by your browser when accessing the data.<\/p><p class=\"mb-0\">Anyhow if you use this functionality you agree to my <a href=\"https:\/\/mseiche.de\/terms-of-service\">Terms of Service<\/a><\/p>",
"imageOnlyLinks": {
"visible": true
}
},
"footer": {
"actions": [
{
"type": "popup",
"icon": {
"type": "material",
"name": "privacy_tip"
},
"content": "<div>This page belongs to <a href=\"https:\/\/mseiche.de\" target=\"_blank\">mseiche.de<\/a> therefore the following documents also apply for this page:<ul class=\"mb-0\"><li><a href=\"https:\/\/mseiche.de\/privacy-policy\" target=\"_blank\">Privacy Policy<\/a><\/li><li><a href=\"https:\/\/mseiche.de\/terms-of-service\" target=\"_blank\">Terms of Service<\/a><\/li><li><a href=\"https:\/\/mseiche.de\/about\" target=\"_blank\">About<\/a><\/li><\/ul><\/div>",
"tooltip": "Privacy and Terms of Service"
},
{
"type": "link",
"icon": {
"type": "img",
"src": "assets/images/github.svg",
"width": "28",
"height": "28"
},
"href": "https://github.com/Hakenadu/plantuml-editor",
"tooltip": "View the code for this page on GitHub"
},
{
"type": "link",
"icon": {
"type": "img",
"src": "assets/images/mseiche.svg",
"width": "28",
"height": "28"
},
"href": "https://mseiche.de",
"tooltip": "Visit my main page"
}
]
}
}
If share links are enabled you need to provide the "share" configuration entry to make the share button appear. You may provide a custom description for the share dialog using the share.description configuration entry. This can especially be useful, if you need to link custom terms of service.
The following types of actions are supported:
- popup contains a custom html template which will be shown in a popup menu after clicking the generated action button
- link opens a provided link in a new tab after clicking the generated action button
each action can be parameterized with the following attributes:
- tooltip (optional) contains a text which will be shown while hovering the generated action button
- icon controls the appearance of the generated action button
Currently two types of icons are supported:
- material shows a google material icon by its name
- img shows an image using an img tag and a resource uri
docker run -d -p 80:8080 --name plantuml-editor -v /path/to/your/frontend-config.json:/opt/config/frontend-config.json hakenadu/plantuml-editor
For enabling sharing using base64 you just need to provide the share object in the frontend-config.json
plantuml-editor:
image: hakenadu/plantuml-editor
container_name: plantuml-editor
ports:
- 80:8080
volumes:
- /path/to/your/frontend-config.json:/opt/config/frontend-config.json
For enabling share links you may provide a WebDAV interface for the plantuml-editor. The following docker-compose example shows a maximal example.
version: '3'
services:
plantuml-editor:
image: hakenadu/plantuml-editor
container_name: plantuml-editor
environment:
# MANDATORY VARIABLES
SPRING_PROFILES_ACTIVE: webdav # activate the /documents endpoint using webdav
WEBDAV_URL: http://plantuml-editor-webdav:80 # url to the webdav interface
WEBDAV_USERNAME: john # basic auth webdav username
WEBDAV_PASSWORD: doe1337 # basic auth webdav password
# OPTIONAL VARIABLES
DOCUMENT_SALT: my-fancy-at-least-8-bytes-long-salt # salt for symmetrically encrypting document content
DOCUMENT_LIFETIME: PT168H # the maximum age for stored documents (defaults to 7 days)
DOCUMENT_REAPER_CRON: '0 0/10 * * * ?' # the cron definition which determines the frequency for the document reaper to delete old documents (defaults to 10 minutes)
DOCUMENT_OVERRIDING_ENABLED: false # if true the document may be overridden by someone who knows the id (for collaborations)
WEBDAV_COLLECTION: # if passed, an existing webdav collection will be used
ports:
- 80:8080
volumes:
- /path/to/your/frontend-config.json:/opt/config/frontend-config.json
plantuml-editor-webdav:
image: bytemark/webdav
container_name: plantuml-editor-webdav
environment:
USERNAME: john # basic auth webdav username
PASSWORD: doe1337 # basic auth webdav password
For enabling share links you may also provide a Redis interface for the plantuml-editor. The following docker-compose example shows a maximal example.
version: '3'
services:
plantuml-editor:
image: hakenadu/plantuml-editor
container_name: plantuml-editor
environment:
# MANDATORY VARIABLES
SPRING_PROFILES_ACTIVE: redis
REDIS_HOST: plantuml-editor-redis
REDIS_PASSWORD: doe1337 # use a better one ;-)
# OPTIONAL VARIABLES
REDIS_PORT: 6379
REDIS_PREFIX: /documents/ # prefix for persisted values
DOCUMENT_SALT: my-fancy-at-least-8-bytes-long-salt # salt for symmetrically encrypting document content
DOCUMENT_LIFETIME: PT168H # the maximum age for stored documents (defaults to 7 days)
DOCUMENT_OVERRIDING_ENABLED: false # if true the document may be overridden by someone who knows the id (for collaborations)
ports:
- 80:8080
volumes:
- /path/to/your/frontend-config.json:/opt/config/frontend-config.json
plantuml-editor-redis:
image: bitnami/redis # or registry.redhat.io/rhel8/redis-5:1-144
container_name: plantuml-editor-redis
environment:
REDIS_PASSWORD: doe1337 # use a better one ;-)
This is an example for running the plantuml-editor with AI driven Completions using the OpenAI API. If you also want to run WebDAV or Redis you may also add the Environment Variables from the previous examples and join the SPRING_PROFILES_ACTIVE variables by comma (f. e. webdav,completion or redis,completion)
version: '3'
services:
plantuml-editor:
image: hakenadu/plantuml-editor
container_name: plantuml-editor
environment:
# MANDATORY VARIABLES
SPRING_PROFILES_ACTIVE: completion
OPENAI_API_KEY: sk-thisistherestofmyapikey
# OPTIONAL VARIABLES
OPENAI_MODEL: gpt-3.5-turbo # currently only chat models are supported
OPENAI_MAX_TOKENS: 1000
# OPENAI_SYSTEM_SCOPE: allows to set the models system context (take a look at plantuml-editor-backend/src/main/resources/application-completion.yml)
# OPENAI_PROMPT_PATTERN: allows to set the models prompt pattern (take a look at plantuml-editor-backend/src/main/resources/application-completion.yml)
ports:
- 80:8080