From 285f274f40dbbe82c11b2fcff2c3de63eb091e81 Mon Sep 17 00:00:00 2001 From: Rudra Patel Date: Mon, 6 Jan 2025 23:28:26 -0500 Subject: [PATCH 1/2] feat: Prepare extension for publication --- .github/workflows/pr.yml | 50 +++++++++++++++++ .vscode/launch.json | 4 -- .vscode/tasks.json | 2 - .vscodeignore | 6 +-- CHANGELOG.md | 11 ++-- README.md | 66 +++++------------------ package.json | 6 +-- src/extension.ts | 6 +-- src/logger.ts | 4 +- src/{ => types}/prettier-plugin-java.d.ts | 0 src/utils.ts | 4 +- 11 files changed, 80 insertions(+), 79 deletions(-) create mode 100644 .github/workflows/pr.yml rename src/{ => types}/prettier-plugin-java.d.ts (100%) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml new file mode 100644 index 0000000..fa4746f --- /dev/null +++ b/.github/workflows/pr.yml @@ -0,0 +1,50 @@ +name: pr-check + +on: + pull_request: + types: + # default types + - opened + - reopened + - synchronize + # run when PR title or body changes + - edited + branches: + - main +jobs: + lint-and-format: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ github.head_ref }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "lts/iron" + cache: "npm" + + - name: Install dependencies + run: npm install + + - name: Check that project is able to be packaged + run: npm run package + + - name: Check that PR title follows conventional commits using regex + env: + TITLE: ${{ github.event.pull_request.title }} + run: | + echo "Your PR title is '$TITLE'" + + regex="(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(\([a-z[[:space:]]+\))?:[[:space:]].+" + + if [[ $TITLE =~ $regex ]]; then + echo "PR title follows conventional commits" + else + echo "PR title does not follow conventional commits format" + echo "Prefix your PR title with a descriptor such as 'feat:' and then summarize your change" + echo "See the following link for more information: https://www.conventionalcommits.org/en/v1.0.0/" + exit 1 + fi diff --git a/.vscode/launch.json b/.vscode/launch.json index c42edc0..81b773f 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,7 +1,3 @@ -// A launch configuration that compiles the extension and then opens it inside a new window -// Use IntelliSense to learn about possible attributes. -// Hover to view descriptions of existing attributes. -// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 { "version": "0.2.0", "configurations": [ diff --git a/.vscode/tasks.json b/.vscode/tasks.json index a425a85..b4ae625 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,5 +1,3 @@ -// See https://go.microsoft.com/fwlink/?LinkId=733558 -// for the documentation about the tasks.json format { "version": "2.0.0", "tasks": [ diff --git a/.vscodeignore b/.vscodeignore index 826face..de1daf0 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -1,11 +1,11 @@ +.github/** .vscode/** -out/** +dist/** node_modules/** src/** .gitignore -.yarnrc +.prettierrc esbuild.js -vsc-extension-quickstart.md **/tsconfig.json **/eslint.config.mjs **/*.map diff --git a/CHANGELOG.md b/CHANGELOG.md index 4139ba6..5bd1ed1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,10 @@ -# Change Log +# Changelog -All notable changes to the "prettier-plugin-java-vscode" extension will be documented in this file. +All notable changes to this project will be documented in this file. -Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [1.0.0] -- Initial release \ No newline at end of file +- Initial release diff --git a/README.md b/README.md index 928fb4e..2451511 100644 --- a/README.md +++ b/README.md @@ -1,71 +1,29 @@ # prettier-plugin-java-vscode README -This is the README for your extension "prettier-plugin-java-vscode". After writing up a brief description, we recommend including the following sections. +A VSCode extension to format Java files with Prettier using prettier-plugin-java. ## Features -Describe specific features of your extension including screenshots of your extension in action. Image paths are relative to this README file. - -For example if there is an image subfolder under your extension project workspace: - -\!\[feature X\]\(images/feature-x.png\) - -> Tip: Many popular extensions utilize animations. This is an excellent way to show off your extension! We recommend short, focused animations that are easy to follow. - -## Requirements - -If you have any requirements or dependencies, add a section describing those and how to install and configure them. +- Format Java files with no configuration necessary +- Specify a Prettier config file to use if desired ## Extension Settings -Include if your extension adds any VS Code settings through the `contributes.configuration` extension point. +To set this formatter as the default formatter for Java files, add the following to your VSCode settings: -For example: +```json +"[java]": { + "editor.defaultFormatter": "RudraPatel.prettier-plugin-java-vscode" + } +``` This extension contributes the following settings: -* `myExtension.enable`: Enable/disable this extension. -* `myExtension.thing`: Set to `blah` to do something. - -## Known Issues - -Calling out known issues can help limit users opening duplicate issues against your extension. +- `prettier-plugin-java-vscode.enabled`: Enable/disable the plugin. +- `prettier-plugin-java-vscode.prettierConfigPath`: Provide a absolution path to your prettier configuration file. ## Release Notes -Users appreciate release notes as you update your extension. - ### 1.0.0 -Initial release of ... - -### 1.0.1 - -Fixed issue #. - -### 1.1.0 - -Added features X, Y, and Z. - ---- - -## Following extension guidelines - -Ensure that you've read through the extensions guidelines and follow the best practices for creating your extension. - -* [Extension Guidelines](https://code.visualstudio.com/api/references/extension-guidelines) - -## Working with Markdown - -You can author your README using Visual Studio Code. Here are some useful editor keyboard shortcuts: - -* Split the editor (`Cmd+\` on macOS or `Ctrl+\` on Windows and Linux). -* Toggle preview (`Shift+Cmd+V` on macOS or `Shift+Ctrl+V` on Windows and Linux). -* Press `Ctrl+Space` (Windows, Linux, macOS) to see a list of Markdown snippets. - -## For more information - -* [Visual Studio Code's Markdown Support](http://code.visualstudio.com/docs/languages/markdown) -* [Markdown Syntax Reference](https://help.github.com/articles/markdown-basics/) - -**Enjoy!** +- Initial release diff --git a/package.json b/package.json index fbfd126..05933aa 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "prettier-plugin-java-vscode", - "displayName": "prettier-plugin-java For VSCode", - "description": "A VSCode plugin that uses prettier-plugin-java to format .java files. Based on the now removed mwpb.java-prettier-formatter extension.", + "displayName": "Prettier Java Plugin", + "description": "A VSCode extension to format Java files with Prettier using prettier-plugin-java.", "version": "1.0.0", "publisher": "RudraPatel", "license": "MIT", @@ -43,7 +43,7 @@ } ], "configuration": { - "title": "Prettier Plugin Java VSCode", + "title": "Prettier Java Plugin", "properties": { "prettier-plugin-java-vscode.prettierConfigPath": { "type": ["string", "null"], diff --git a/src/extension.ts b/src/extension.ts index 3912c81..14c2144 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -21,7 +21,7 @@ async function formatJavaDocument( const isEnabled = checkIfEnabled(); if (!isEnabled) { - log("Prettier Plugin Java VSCode is disabled"); + log("Prettier Plugin Java VSCode is disabled\n"); return null; } @@ -50,13 +50,13 @@ async function formatJavaDocument( const elapsedTime = Date.now() - start; - log(`Formatted ${document.fileName} in ${elapsedTime}ms.`); + log(`Formatted ${document.fileName} in ${elapsedTime}ms\n`); return [TextEdit.replace(entireDocumentRange, formattedText)]; } export function activate(context: ExtensionContext) { - log("Prettier Plugin Java VSCode activated."); + log("Prettier Plugin Java VSCode activated\n"); const disposable = languages.registerDocumentFormattingEditProvider("java", { provideDocumentFormattingEdits: formatJavaDocument, diff --git a/src/logger.ts b/src/logger.ts index 1e7c7e5..4649b18 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -1,9 +1,7 @@ import { window } from "vscode"; // Create the output channel once at the module level -export const outputChannel = window.createOutputChannel( - "Prettier Plugin Java VSCode", -); +export const outputChannel = window.createOutputChannel("Prettier Java Plugin"); function getFormattedTime(): string { return new Date().toLocaleTimeString("en-US"); diff --git a/src/prettier-plugin-java.d.ts b/src/types/prettier-plugin-java.d.ts similarity index 100% rename from src/prettier-plugin-java.d.ts rename to src/types/prettier-plugin-java.d.ts diff --git a/src/utils.ts b/src/utils.ts index 36d5030..a52989f 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -31,7 +31,7 @@ async function getPretterConfigPath(document: TextDocument): Promise { if (!fileExists) { log( - `Specified Prettier config file (${userProvidedConfigPath}) does not exist.`, + `Specified Prettier config file (${userProvidedConfigPath}) does not exist`, ); log( `Prettier will attempt to resolve the config file from the document file name (${document.fileName})`, @@ -45,7 +45,7 @@ async function getPretterConfigPath(document: TextDocument): Promise { return userProvidedConfigPath; } - log("No specified Prettier config file."); + log("No specified Prettier config file"); log( `Prettier will attempt to resolve the config file from the document file name (${document.fileName})`, ); From 9e1c6e65ed0d7eeda79a313d102dbdd661afb129 Mon Sep 17 00:00:00 2001 From: Rudra Patel Date: Mon, 6 Jan 2025 23:53:43 -0500 Subject: [PATCH 2/2] feat: Fix .vsix import issue --- .gitignore | 2 +- .vscodeignore | 15 +++++------ LICENSE | 21 ++++++++++++++++ README.md | 2 +- icon.png | Bin 0 -> 5417 bytes package.json | 5 ++-- vsc-extension-quickstart.md | 48 ------------------------------------ 7 files changed, 34 insertions(+), 59 deletions(-) create mode 100644 LICENSE create mode 100644 icon.png delete mode 100644 vsc-extension-quickstart.md diff --git a/.gitignore b/.gitignore index 747d976..d2703e4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ node_modules dist -.vsix +*.vsix diff --git a/.vscodeignore b/.vscodeignore index de1daf0..3862469 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -1,12 +1,13 @@ -.github/** -.vscode/** -dist/** +.github +.vscode node_modules/** +!node_modules/prettier src/** +**/*.map .gitignore .prettierrc esbuild.js -**/tsconfig.json -**/eslint.config.mjs -**/*.map -**/*.ts +eslint.config.mjs +package-lock.json +tsconfig.json +*.vsix \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..aef5298 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) [2025] [Rudra Patel] + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index 2451511..31d5e39 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# prettier-plugin-java-vscode README +# Prettier Java Plugin A VSCode extension to format Java files with Prettier using prettier-plugin-java. diff --git a/icon.png b/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..71f2515b7b7e6b7236d34c46648edf7b8f1ce2c5 GIT binary patch literal 5417 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