Skip to content

Commit

Permalink
Create plugin (still stuff to do)
Browse files Browse the repository at this point in the history
  • Loading branch information
WarningImHack3r committed Jan 3, 2024
1 parent 02406e3 commit 962d90f
Show file tree
Hide file tree
Showing 31 changed files with 784 additions and 180 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
.idea
.qodana
build
.DS_Store
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
<!-- Keep a Changelog guide -> https://keepachangelog.com -->
<!-- Types of changes memo:
— “Added” for new features.
— “Changed” for changes in existing functionality.
— “Deprecated” for soon-to-be removed features.
— “Removed” for now removed features.
— “Fixed” for any bug fixes.
— “Security” in case of vulnerabilities.
-->

# intellij-shadcn-plugin Changelog

## [Unreleased]

### Added
- Initial scaffold created from [IntelliJ Platform Plugin Template](https://github.com/JetBrains/intellij-platform-plugin-template)
- Initial release
38 changes: 23 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,36 @@
# intellij-shadcn-plugin

![Build](https://github.com/WarningImHack3r/intellij-shadcn-plugin/workflows/Build/badge.svg)
[![Version](https://img.shields.io/jetbrains/plugin/v/PLUGIN_ID.svg)](https://plugins.jetbrains.com/plugin/PLUGIN_ID)
[![Downloads](https://img.shields.io/jetbrains/plugin/d/PLUGIN_ID.svg)](https://plugins.jetbrains.com/plugin/PLUGIN_ID)
[![Version](https://img.shields.io/jetbrains/plugin/v/com.github.warningimhack3r.intellijshadcnplugin.svg)](https://plugins.jetbrains.com/plugin/com.github.warningimhack3r.intellijshadcnplugin)
[![Downloads](https://img.shields.io/jetbrains/plugin/d/com.github.warningimhack3r.intellijshadcnplugin.svg)](https://plugins.jetbrains.com/plugin/com.github.warningimhack3r.intellijshadcnplugin)

## Template ToDo list
- [x] Create a new [IntelliJ Platform Plugin Template][template] project.
- [ ] Get familiar with the [template documentation][template].
- [ ] Adjust the [pluginGroup](./gradle.properties), [plugin ID](./src/main/resources/META-INF/plugin.xml) and [sources package](./src/main/kotlin).
- [ ] Adjust the plugin description in `README` (see [Tips][docs:plugin-description])
- [ ] Review the [Legal Agreements](https://plugins.jetbrains.com/docs/marketplace/legal-agreements.html?from=IJPluginTemplate).
- [ ] [Publish a plugin manually](https://plugins.jetbrains.com/docs/intellij/publishing-plugin.html?from=IJPluginTemplate) for the first time.
- [ ] Set the `PLUGIN_ID` in the above README badges.
- [ ] Set the [Plugin Signing](https://plugins.jetbrains.com/docs/intellij/plugin-signing.html?from=IJPluginTemplate) related [secrets](https://github.com/JetBrains/intellij-platform-plugin-template#environment-variables).
- [ ] Set the [Deployment Token](https://plugins.jetbrains.com/docs/marketplace/plugin-upload.html?from=IJPluginTemplate).
- [ ] Click the <kbd>Watch</kbd> button on the top of the [IntelliJ Platform Plugin Template][template] to be notified about releases containing new features and fixes.

## Description
<!-- Plugin description -->
This Fancy IntelliJ Platform Plugin is going to be your implementation of the brilliant ideas that you have.

This specific section is a source for the [plugin.xml](/src/main/resources/META-INF/plugin.xml) file which will be extracted by the [Gradle](/build.gradle.kts) during the build process.

To keep everything working, do not remove `<!-- ... -->` sections.
Manage your shadcn/ui components in your project.

This plugin will help you manage your shadcn/ui components through a simple tool window. Add, remove, update them with a single click.

## Features
- Automatically detect shadcn/ui components in your project
- Instantly add, remove, update them with a single click
- Refreshes on opening the tool window
- Supports _all_ shadcn/ui implementations: Svelte, React, Vue, Solid, and even Kotlin/JS
- Browse available components
- Easily search for remote or existing components
- (Soon) support monorepos
- ...and more!

## Usage
Simply open the `shadcn/ui` tool window and start managing your components.
If you don't see the tool window, you can open it from `View > Tool Windows > shadcn/ui`.

## Planned Features
- Add support for monorepos
<!-- Plugin description end -->

## Installation
Expand All @@ -41,4 +50,3 @@ To keep everything working, do not remove `<!-- ... -->` sections.
Plugin based on the [IntelliJ Platform Plugin Template][template].

[template]: https://github.com/JetBrains/intellij-platform-plugin-template
[docs:plugin-description]: https://plugins.jetbrains.com/docs/intellij/plugin-user-experience.html#plugin-description-and-presentation
5 changes: 3 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ fun environment(key: String) = providers.environmentVariable(key)
plugins {
id("java") // Java support
alias(libs.plugins.kotlin) // Kotlin support
kotlin(libs.plugins.serialization.get().pluginId) version libs.versions.kotlin // Kotlin Serialization support
alias(libs.plugins.gradleIntelliJPlugin) // Gradle IntelliJ Plugin
alias(libs.plugins.changelog) // Gradle Changelog Plugin
alias(libs.plugins.qodana) // Gradle Qodana Plugin
Expand All @@ -19,18 +20,18 @@ version = properties("pluginVersion").get()
// Configure project's dependencies
repositories {
mavenCentral()
gradlePluginPortal()
}

// Dependencies are managed with Gradle version catalog - read more: https://docs.gradle.org/current/userguide/platforms.html#sub:version-catalog
dependencies {
// implementation(libs.annotations)
}

// Set the JVM language level used to build the project. Use Java 11 for 2020.3+, and Java 17 for 2022.2+.
kotlin {
@Suppress("UnstableApiUsage")
jvmToolchain {
languageVersion = JavaLanguageVersion.of(17)
languageVersion = JavaLanguageVersion.of(11)
vendor = JvmVendorSpec.JETBRAINS
}
}
Expand Down
8 changes: 4 additions & 4 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ pluginGroup = com.github.warningimhack3r.intellijshadcnplugin
pluginName = intellij-shadcn-plugin
pluginRepositoryUrl = https://github.com/WarningImHack3r/intellij-shadcn-plugin
# SemVer format -> https://semver.org
pluginVersion = 0.0.1
pluginVersion = 1.0.0

# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
pluginSinceBuild = 223
pluginUntilBuild = 233.*
pluginSinceBuild = 212
pluginUntilBuild =

# IntelliJ Platform Properties -> https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#configuration-intellij-extension
platformType = IC
platformVersion = 2022.3.3
platformVersion = 2021.3

# Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html
# Example: platformPlugins = com.intellij.java, com.jetbrains.php:203.4449.22
Expand Down
8 changes: 1 addition & 7 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
[versions]
# libraries
annotations = "24.1.0"

# plugins
kotlin = "1.9.22"
changelog = "2.2.0"
gradleIntelliJPlugin = "1.16.1"
qodana = "0.1.13"
kover = "0.7.5"

[libraries]
annotations = { group = "org.jetbrains", name = "annotations", version.ref = "annotations" }

[plugins]
changelog = { id = "org.jetbrains.changelog", version.ref = "changelog" }
gradleIntelliJPlugin = { id = "org.jetbrains.intellij", version.ref = "gradleIntelliJPlugin" }
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
serialization = { id = "plugin.serialization", version.ref = "kotlin" }
kover = { id = "org.jetbrains.kotlinx.kover", version.ref = "kover" }
qodana = { id = "org.jetbrains.qodana", version.ref = "qodana" }
2 changes: 1 addition & 1 deletion qodana.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

version: 1.0
linter: jetbrains/qodana-jvm-community:latest
projectJDK: "17"
projectJDK: "11"
profile:
name: qodana.recommended
exclude:
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.github.warningimhack3r.intellijshadcnplugin.backend

import com.github.warningimhack3r.intellijshadcnplugin.backend.helpers.FileManager
import com.github.warningimhack3r.intellijshadcnplugin.backend.sources.ISPSource
import com.github.warningimhack3r.intellijshadcnplugin.backend.sources.ISPSvelteSource
import com.intellij.openapi.project.Project

object ISPScanner {

fun findShadcnImplementation(project: Project): ISPSource? {
FileManager(project).getVirtualFilesByName("components.json").firstOrNull()?.let { componentsJson ->
val contents = componentsJson.contentsToByteArray().decodeToString()
if (contents.contains("shadcn-svelte.com")) {
return ISPSvelteSource(project)
}
}
// TODO: Add other sources
return null
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.github.warningimhack3r.intellijshadcnplugin.backend.helpers

import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiFile
import com.intellij.psi.search.FilenameIndex
import com.intellij.psi.search.GlobalSearchScope
import java.nio.file.NoSuchFileException

class FileManager(private val project: Project) {
fun saveFileAtPath(file: PsiFile, path: String) {
var deepest = getDeepestFileForPath(path)
val deepestRelativePath = deepest.path.substringAfter("${project.basePath!!}/")
path.substringAfter(deepestRelativePath).split('/').filterNot { it.isEmpty() }.forEach { subdirectory ->
deepest = deepest.createChildDirectory(this, subdirectory)
}
deepest.createChildData(this, file.name).apply {
setBinaryContent(file.text.toByteArray())
}
}

fun deleteFileAtPath(path: String): Boolean {
return getFileAtPath(path)?.delete(this)?.let { true } ?: false
}

fun getVirtualFilesByName(name: String): Collection<VirtualFile> {
return FilenameIndex.getVirtualFilesByName(
name,
GlobalSearchScope.projectScope(project)
).filter { file ->
val nodeModule = file.path.contains("node_modules")
if (!name.startsWith(".")) {
!nodeModule && !file.path.substringAfter(project.basePath!!).startsWith(".")
} else !nodeModule
}
}

private fun getDeepestFileForPath(filePath: String): VirtualFile {
var paths = filePath.split('/')
var currentFile = getVirtualFilesByName(paths.first()).firstOrNull() ?: throw NoSuchFileException("No file found at path $filePath")
paths = paths.drop(1)
for (path in paths) {
val child = currentFile.findChild(path)
if (child == null) {
return currentFile
} else {
currentFile = child
}
}
return currentFile
}

fun getFileAtPath(filePath: String): VirtualFile? {
try {
val deepest = getDeepestFileForPath(filePath)
return if (deepest.name == filePath.substringAfterLast('/')) deepest else null
} catch (e: Exception) {
return null
}
}

fun getFileContentsAtPath(path: String): String? {
return getFileAtPath(path)?.contentsToByteArray()?.decodeToString()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.github.warningimhack3r.intellijshadcnplugin.backend.helpers

import com.intellij.openapi.project.Project
import com.jetbrains.rd.util.printlnError
import java.io.File

class ShellRunner(private val project: Project? = null) {
private val failedCommands = mutableSetOf<String>()

private fun isWindows() = System.getProperty("os.name").lowercase().contains("win")

fun execute(command: Array<String>): String? {
val commandName = command.firstOrNull() ?: return null
if (isWindows() && failedCommands.contains(commandName)) {
command[0] = "$commandName.cmd"
}
return try {
val process = ProcessBuilder(*command)
.redirectOutput(ProcessBuilder.Redirect.PIPE)
.directory(project?.basePath?.let { File(it) })
.start()
process.waitFor()
process.inputStream.bufferedReader().readText()
} catch (e: Exception) {
if (isWindows() && !commandName.endsWith(".cmd")) {
failedCommands.add(commandName)
return execute(arrayOf("$commandName.cmd") + command.drop(1).toTypedArray())
}
printlnError("Error while executing \"${command.joinToString(" ")}\": ${e.message}")
null
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.github.warningimhack3r.intellijshadcnplugin.backend.http

import java.net.HttpURLConnection
import java.net.URL

// Credit to: https://gist.github.com/GrzegorzDyrda/be47602fc855a52fba240dd2c2adc2d5
object RequestSender {

/**
* Sends an HTTP request to the given [url], using the given HTTP [method]. The request can also
* include custom [headers] and [body].
*
* Returns the [Response] object containing [statusCode][Response.statusCode],
* [headers][Response.headers] and [body][Response.body].
*/
fun sendRequest(url: String, method: String = "GET", headers: Map<String, String>? = null, body: String? = null): Response {
val conn = URL(url).openConnection() as HttpURLConnection

with(conn) {
requestMethod = method
doOutput = body != null
headers?.forEach(::setRequestProperty)
}

if (body != null) {
conn.outputStream.use {
it.write(body.toByteArray())
}
}

val responseBody = conn.inputStream.use { it.readBytes() }.toString(Charsets.UTF_8)

return Response(conn.responseCode, conn.headerFields, responseBody)
}

data class Response(val statusCode: Int, val headers: Map<String, List<String>>? = null, val body: String? = null)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.github.warningimhack3r.intellijshadcnplugin.backend.sources

data class ISPComponent(
val name: String,
val description: String? = null
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.github.warningimhack3r.intellijshadcnplugin.backend.sources

interface ISPSource {

var domain: String
var language: String

fun fetchAllComponents(): List<ISPComponent>

fun fetchAllStyles(): List<ISPStyle>

fun getInstalledComponents(): List<String>

fun addComponent(componentName: String)

fun isComponentUpToDate(componentName: String): Boolean

fun removeComponent(componentName: String)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.github.warningimhack3r.intellijshadcnplugin.backend.sources

data class ISPStyle(
val name: String,
val label: String
)
Loading

0 comments on commit 962d90f

Please sign in to comment.