From 9de3112770ba9015a34ce0e593d3d6c30c620acb Mon Sep 17 00:00:00 2001 From: Pavel Bodiachevskii Date: Sat, 7 Sep 2024 22:35:11 +0400 Subject: [PATCH] feat(preview panel): render specification --- .../AsyncAPISpecificationHtmlRenderer.kt | 60 ++++++++++++++----- .../editor/preview/AsyncAPIPreviewEditor.kt | 14 +++-- .../preview/AsyncAPIPreviewEditorProvider.kt | 2 +- 3 files changed, 54 insertions(+), 22 deletions(-) diff --git a/src/main/kotlin/com/asyncapi/plugin/idea/_core/AsyncAPISpecificationHtmlRenderer.kt b/src/main/kotlin/com/asyncapi/plugin/idea/_core/AsyncAPISpecificationHtmlRenderer.kt index 2120779..790e3d7 100644 --- a/src/main/kotlin/com/asyncapi/plugin/idea/_core/AsyncAPISpecificationHtmlRenderer.kt +++ b/src/main/kotlin/com/asyncapi/plugin/idea/_core/AsyncAPISpecificationHtmlRenderer.kt @@ -8,11 +8,13 @@ import com.fasterxml.jackson.dataformat.yaml.YAMLFactory import com.intellij.json.JsonFileType import com.intellij.openapi.components.Service import com.intellij.openapi.components.service +import com.intellij.openapi.editor.Document import com.intellij.openapi.vfs.LocalFileSystem import com.intellij.openapi.vfs.VirtualFile import io.netty.handler.codec.http.FullHttpRequest import org.jetbrains.yaml.YAMLFileType import java.io.File +import java.net.URL /** * @author Pavel Bodiachevskii @@ -28,6 +30,20 @@ class AsyncAPISpecificationHtmlRenderer { private val specificationTemplateCssUrl = "default.min.css" private val specificationTemplateJsUrl = "index.js" + fun render(specificationVirtualFile: VirtualFile, document: Document?): String { + if (specificationVirtualFile.fileType !is YAMLFileType && specificationVirtualFile.fileType !is JsonFileType) { + return "specification: ${specificationVirtualFile.name} not in json or yaml format." + } + + val isJson = specificationVirtualFile.fileType is JsonFileType + val specification = replaceLocalReferences(document?.text ?: "", specificationVirtualFile, isJson) + + val specificationTemplate = this.javaClass.getResource(specificationTemplateUrl) + specificationTemplate ?: return "specification template not found." + + return composePage(specificationTemplate, specification) + } + fun render(request: FullHttpRequest, specificationUrl: String?): String { specificationUrl ?: return "specification: not found." @@ -53,21 +69,7 @@ class AsyncAPISpecificationHtmlRenderer { supplier = { specificationVirtualFile } ) - return specificationTemplate.readText(Charsets.UTF_8) - .replace( - "schema: {},", - "schema: $specification," - ) - .replace( - "", - "" - ).replace( - "", - "" - ).replace( - "", - webSocket?.toString() ?: "" - ) + return composePage(specificationTemplate, specification, webSocket) } fun replaceLocalReferences(specification: String, specificationFile: VirtualFile, isJson: Boolean): String { @@ -100,4 +102,32 @@ class AsyncAPISpecificationHtmlRenderer { return urlProvider.reference(referencedFile.path, specificationComponentReference) } + private fun composePage( + specificationTemplate: URL, + specification: String, + webSocket: CharSequence? = null + ): String { + val page = specificationTemplate.readText(Charsets.UTF_8) + .replace( + "schema: {},", + "schema: $specification," + ) + .replace( + "", + "" + ).replace( + "", + "" + ) + + return if (webSocket != null) { + page.replace( + "", + webSocket.toString() + ) + } else { + page + } + } + } \ No newline at end of file diff --git a/src/main/kotlin/com/asyncapi/plugin/idea/extensions/editor/preview/AsyncAPIPreviewEditor.kt b/src/main/kotlin/com/asyncapi/plugin/idea/extensions/editor/preview/AsyncAPIPreviewEditor.kt index cc02a7d..3c453de 100644 --- a/src/main/kotlin/com/asyncapi/plugin/idea/extensions/editor/preview/AsyncAPIPreviewEditor.kt +++ b/src/main/kotlin/com/asyncapi/plugin/idea/extensions/editor/preview/AsyncAPIPreviewEditor.kt @@ -1,19 +1,19 @@ package com.asyncapi.plugin.idea.extensions.editor.preview +import com.asyncapi.plugin.idea._core.AsyncAPISpecificationHtmlRenderer import com.asyncapi.plugin.idea.extensions.editor.ui.AsyncAPIJCEFHtmlPanel import com.intellij.codeHighlighting.BackgroundEditorHighlighter import com.intellij.ide.structureView.StructureViewBuilder +import com.intellij.openapi.components.service import com.intellij.openapi.editor.Document import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.event.DocumentEvent import com.intellij.openapi.editor.event.DocumentListener -import com.intellij.openapi.fileEditor.FileEditor -import com.intellij.openapi.fileEditor.FileEditorLocation -import com.intellij.openapi.fileEditor.FileEditorState -import com.intellij.openapi.fileEditor.FileEditorStateLevel +import com.intellij.openapi.fileEditor.* import com.intellij.openapi.project.Project import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.UserDataHolderBase +import com.intellij.openapi.vfs.VirtualFile import java.awt.LayoutManager import java.beans.PropertyChangeListener import javax.swing.JComponent @@ -21,6 +21,7 @@ import javax.swing.JPanel import javax.swing.OverlayLayout class AsyncAPIPreviewEditor( + private val file: VirtualFile, private val document: Document?, private val project: Project ) : @@ -31,6 +32,7 @@ class AsyncAPIPreviewEditor( private val asyncAPIPreviewEditorComponent: JComponent private val htmlPanel: AsyncAPIJCEFHtmlPanel = AsyncAPIJCEFHtmlPanel(editor) + private val specificationHtmlRenderer = service() init { asyncAPIPreviewEditorComponent = createComponent() @@ -38,7 +40,7 @@ class AsyncAPIPreviewEditor( val documentListenerHandler = object : DocumentListener { override fun documentChanged(event: DocumentEvent) { if (asyncAPIPreviewEditorComponent.isVisible && asyncAPIPreviewEditorComponent.isDisplayable) { - htmlPanel.setHtml("${document?.text}") + htmlPanel.setHtml(specificationHtmlRenderer.render(file, document)) } } } @@ -50,7 +52,7 @@ class AsyncAPIPreviewEditor( val overlay: LayoutManager = OverlayLayout(previewEditor) previewEditor.setLayout(overlay) - htmlPanel.setHtml("${document?.text}") + htmlPanel.setHtml(specificationHtmlRenderer.render(file, document)) previewEditor.add(htmlPanel.component) return previewEditor diff --git a/src/main/kotlin/com/asyncapi/plugin/idea/extensions/editor/preview/AsyncAPIPreviewEditorProvider.kt b/src/main/kotlin/com/asyncapi/plugin/idea/extensions/editor/preview/AsyncAPIPreviewEditorProvider.kt index 59ee9e1..5e39d7a 100644 --- a/src/main/kotlin/com/asyncapi/plugin/idea/extensions/editor/preview/AsyncAPIPreviewEditorProvider.kt +++ b/src/main/kotlin/com/asyncapi/plugin/idea/extensions/editor/preview/AsyncAPIPreviewEditorProvider.kt @@ -18,7 +18,7 @@ class AsyncAPIPreviewEditorProvider: WeighedFileEditorProvider() { } override fun createEditor(project: Project, file: VirtualFile): FileEditor { - return AsyncAPIPreviewEditor(FileDocumentManager.getInstance().getDocument(file), project) + return AsyncAPIPreviewEditor(file, FileDocumentManager.getInstance().getDocument(file), project) } override fun getEditorTypeId(): String {