Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Markdown Rendering in the What's New Panel #432

Merged
merged 30 commits into from
Jul 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
9ee9356
Add ChangelogParser
Jun 27, 2023
f9a0fcf
Write tests for ChangelogParser
Jun 27, 2023
cb8dab5
More test cases with changelog and previous latest entry components.
Jun 28, 2023
a8bdc6b
Test case for if previous entry is not null but present in the changelog
Jun 28, 2023
9a04906
Add comments
Jun 28, 2023
4ff0d3c
spotless Apply
Jun 28, 2023
7839e03
Update ChangeLogParser.kt readability.
kateliu20 Jun 28, 2023
e88b058
Using Raw Strings for readability
kateliu20 Jun 28, 2023
c7bcdaf
merge comments and function names
Jun 28, 2023
85f12da
Merge remote-tracking branch 'origin/kl/change_log_parser' into kl/ch…
Jun 28, 2023
0e4f3be
merge comments and function names
Jun 28, 2023
06f3b2a
remove the word "test" in all the test functions
Jun 28, 2023
37f1b00
Documentation added for ChangelogParser
Jun 28, 2023
8bd4eea
Raw Strings
Jun 28, 2023
af7b9b5
Change test for one entry but no previous entries, original input had…
Jun 28, 2023
25b11bd
allow for html parsing
Jun 29, 2023
b1bd591
change css for markdown file
Jun 29, 2023
4068600
add italics
Jun 29, 2023
cad5bba
markdown style with css style sheet rules
Jul 5, 2023
7caf5b1
add codeblock formatting
Jul 5, 2023
d45568a
fix padding / margins
Jul 5, 2023
61b1957
merge conflicts
Jul 6, 2023
0a62c70
run spotless
Jul 6, 2023
e26d91e
extended the Markdown plugin extension using MarkdownJCEFHtmlPanel
Jul 7, 2023
2a4348d
Deleted MarkdownStyle.kt because it is now unnecessary, ran spotless …
Jul 7, 2023
1580f11
Remove java versions
Jul 7, 2023
728a44a
Update skate-plugin/build.gradle.kts to .add
kateliu20 Jul 7, 2023
ef81fb1
Added clearer comments, removed nits
Jul 7, 2023
c153bb4
Merge remote-tracking branch 'origin/kl/markdown_rendering' into kl/m…
Jul 7, 2023
89e8992
Add disposable for when tool window is closed
Jul 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion skate-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ intellij {
version.set("2022.2.5")
type.set("IC") // Target IDE Platform

plugins.set(listOf(/* Plugin Dependencies */ ))
plugins.add("org.intellij.plugins.markdown")
}

tasks {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ object ChangelogParser {
}
}
.trimEnd()

// If the changelog substring is blank, set it as null
// If the previous entry equals to the latest entry, or if no date is found,
// use the previous entry date as the latest date instead of the current date.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,25 @@ package com.slack.sgp.intellij
import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.guessProjectDir
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.wm.ToolWindowAnchor
import com.intellij.openapi.wm.ToolWindowManager
import com.slack.sgp.intellij.ui.WhatsNewPanelFactory
import java.util.function.Supplier

interface SkateProjectService {
fun showWhatsNewWindow()
}

/**
* This file's intended purpose is to pass in the changelog file from the file path into the What's
* New UI of the Skate Plugin
*/
class SkateProjectServiceImpl(private val project: Project) : SkateProjectService {

override fun showWhatsNewWindow() {
// TODO
// Make the file configurable?
// Only show when changed
// Only show latest changes
val settings = project.service<SkatePluginSettings>()
Comment on lines -34 to 42
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can do this in a separate PR but let's make sure we connect these pieces to only show changes since the last update

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes for sure, should I delete these todo comments for now?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say leave 'em until we actually connect the parser to the previously seen state

Expand All @@ -40,13 +45,21 @@ class SkateProjectServiceImpl(private val project: Project) : SkateProjectServic
val changeLogFile = VfsUtil.findRelativeFile(projectDir, settings.whatsNewFilePath) ?: return
val changeLogString = VfsUtil.loadText(changeLogFile)
val toolWindowManager = ToolWindowManager.getInstance(project)

toolWindowManager.invokeLater {
val toolWindow =
toolWindowManager.registerToolWindow("skate-whats-new") {
stripeTitle = Supplier { "What's New in Slack!" }
anchor = ToolWindowAnchor.RIGHT
}
WhatsNewPanelFactory().createToolWindowContent(toolWindow, changeLogString)

// The Disposable is necessary to prevent a substantial memory leak while working with
// MarkdownJCEFHtmlPanel
val parentDisposable = Disposer.newDisposable()

WhatsNewPanelFactory()
.createToolWindowContent(toolWindow, project, changeLogString, parentDisposable)

toolWindow.show()
}
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* Copyright (C) 2023 Slack Technologies, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.slack.sgp.intellij.ui

import com.intellij.openapi.Disposable
import com.intellij.openapi.application.runReadAction
import com.intellij.openapi.project.DumbAware
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.wm.ToolWindow
import com.intellij.testFramework.LightVirtualFile
import com.intellij.ui.content.ContentFactory
import com.intellij.ui.content.ContentManagerEvent
import com.intellij.ui.content.ContentManagerListener
import java.awt.BorderLayout
import javax.swing.JComponent
import javax.swing.JPanel
import org.intellij.lang.annotations.Language
import org.intellij.plugins.markdown.ui.preview.html.MarkdownUtil
import org.intellij.plugins.markdown.ui.preview.jcef.MarkdownJCEFHtmlPanel

/**
* The WhatsNewPanelFactory class takes the markdown file string from SkateService and displays it
* in a tool window. It uses MarkdownJCEFHtmlPanel and has dependency on intellij markdown plugin to
* properly format the markdown file and its contents
*/
class WhatsNewPanelFactory : DumbAware {

// Function that creates the tool window
fun createToolWindowContent(
toolWindow: ToolWindow,
project: Project,
markdownFileString: String,
parentDisposable: Disposable
) {

val toolWindowContent = WhatsNewPanelContent(project, markdownFileString, parentDisposable)
val content =
ContentFactory.getInstance().createContent(toolWindowContent.contentPanel, "", false)
toolWindow.contentManager.addContent(content)
toolWindow.contentManager.addContentManagerListener(
object : ContentManagerListener {
override fun contentRemoved(event: ContentManagerEvent) {
if (event.content.component == toolWindowContent.contentPanel) {
Disposer.dispose(parentDisposable)
toolWindow.contentManager.removeContentManagerListener(this)
}
}
}
)
}

private class WhatsNewPanelContent(
project: Project,
@Language("Markdown") markdownFileString: String,
parentDisposable: Disposable
) {

// Actual panel box for What's New at Slack
val contentPanel: JPanel =
JPanel().apply {
layout = BorderLayout(0, 20)
add(createWhatsNewPanel(project, markdownFileString, parentDisposable), BorderLayout.CENTER)
}

// Control Panel that takes in the current project, markdown string, and a Disposable.
private fun createWhatsNewPanel(
project: Project,
@Language("Markdown") markdownFileString: String,
parentDisposable: Disposable
): JComponent {
// to take in the parsed Changelog:
// val parsedChangelog = ChangelogParser.readFile(markdownFileString)
// then, pass in parsedChangelog instead of markdownFileString

val file = LightVirtualFile("changelog.md", markdownFileString)

val panel = MarkdownJCEFHtmlPanel(project, file)
Disposer.register(parentDisposable, panel)
val html = runReadAction {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for my own knowledge, what's runReadAction do?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that runReadAction is so we can read the markdown content and convert it to html. Here is some documentation for it too: https://plugins.jetbrains.com/docs/intellij/general-threading-rules.html#read-access, and it's used in: https://intellij-support.jetbrains.com/hc/en-us/community/posts/10856308259090-Markdown-Preview-Swing-Component.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, so looking at that first one it's more that it guarantees safe access if we're not on the main thread?

MarkdownUtil.generateMarkdownHtml(file, markdownFileString, project)
}

panel.setHtml(html, 0)
return panel.component
}
}
}
1 change: 1 addition & 0 deletions skate-plugin/src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<!-- Product and plugin compatibility requirements.
Read more: https://plugins.jetbrains.com/docs/intellij/plugin-compatibility.html -->
<depends>com.intellij.modules.platform</depends>
<depends>org.intellij.plugins.markdown</depends>

<!-- Extension points defined by the plugin.
Read more: https://plugins.jetbrains.com/docs/intellij/plugin-extension-points.html -->
Expand Down