Repository: raycast/extensions
Pull request #18574: Update paste-as-plain-text extension
Author: login: kero13ro
Labels: name: extension fix / improvement
description: Label for PRs with extension's fix improvements
name: extension: paste-as-plain-text
description: Issues related to the paste-as-plain-text extension
Created: 2025-04-14T07:50:20Z | Merged: 2025-04-15T05:51:13Z

## Description

Previously, the `Paste as JSON` command only supported **strict JSON strings**, which required quoted keys and double quotes.
```js
{ "foo": "bar", "count": 1 }
```

This update switches to JSON5.parse, enabling support for more flexible object formats such as:
```js
{ foo: 'bar', count: 1 }
{ user: { name: 'Alice', age: 30 }, active: true }
{ items: [1, 2, 3], trailingComma: true, }
```
JSON5.parse parses JavaScript-like objects without evaluating the input as executable code, improving both usability and security.

## Checklist

- [x] I read the [extension guidelines](https://developers.raycast.com/basics/prepare-an-extension-for-store)
- [x] I read the [documentation about publishing](https://developers.raycast.com/basics/publish-an-extension)
- [x] I ran `npm run build` and [tested this distribution build in Raycast](https://developers.raycast.com/basics/prepare-an-extension-for-store#metadata-and-configuration)
- [x] I checked that files in the `assets` folder are used by the extension itself
- [x] I checked that assets used by the `README` are placed outside of the `metadata` folder



Diff:
diff --git a/extensions/paste-as-plain-text/.gitignore b/extensions/paste-as-plain-text/.gitignore
new file mode 100644
index 00000000000..9ff34e3e9f3
--- /dev/null
+++ b/extensions/paste-as-plain-text/.gitignore
@@ -0,0 +1,13 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+
+# Raycast specific files
+raycast-env.d.ts
+.raycast-swift-build
+.swiftpm
+compiled_raycast_swift
+
+# misc
+.DS_Store
diff --git a/extensions/paste-as-plain-text/CHANGELOG.md b/extensions/paste-as-plain-text/CHANGELOG.md
index 7330960eddc..b159fada521 100644
--- a/extensions/paste-as-plain-text/CHANGELOG.md
+++ b/extensions/paste-as-plain-text/CHANGELOG.md
@@ -1,6 +1,10 @@
 # Paste as Plain text Changelog
 
-## [Fix Paste as Number] - :2024-12-03
+## [Function Optimisation] - 2025-04-15
+
+- Update Paste as JSON, support flexible JSON-like inputs.
+
+## [Fix Paste as Number] - 2024-12-03
 
 -  Fix Paste as Number
 
diff --git a/extensions/paste-as-plain-text/package-lock.json b/extensions/paste-as-plain-text/package-lock.json
index cf05a62a2c6..1f8208be4a4 100644
--- a/extensions/paste-as-plain-text/package-lock.json
+++ b/extensions/paste-as-plain-text/package-lock.json
@@ -11,6 +11,7 @@
         "axios": "^1.8.4",
         "cheerio": "^1.0.0",
         "fs-extra": "^11.2.0",
+        "json5": "^2.2.3",
         "validator": "^13.12.0"
       },
       "devDependencies": {
@@ -2488,6 +2489,18 @@
       "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
       "dev": true
     },
+    "node_modules/json5": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+      "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+      "license": "MIT",
+      "bin": {
+        "json5": "lib/cli.js"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
     "node_modules/jsonfile": {
       "version": "6.1.0",
       "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
@@ -4827,6 +4840,11 @@
       "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
       "dev": true
     },
+    "json5": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+      "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="
+    },
     "jsonfile": {
       "version": "6.1.0",
       "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
diff --git a/extensions/paste-as-plain-text/package.json b/extensions/paste-as-plain-text/package.json
index 4589b731afa..f55caad4302 100644
--- a/extensions/paste-as-plain-text/package.json
+++ b/extensions/paste-as-plain-text/package.json
@@ -6,7 +6,8 @@
   "icon": "paste-icon.png",
   "author": "koinzhang",
   "contributors": [
-    "pantajoe"
+    "pantajoe",
+    "kero13"
   ],
   "categories": [
     "Developer Tools",
@@ -129,6 +130,7 @@
     "axios": "^1.8.4",
     "cheerio": "^1.0.0",
     "fs-extra": "^11.2.0",
+    "json5": "^2.2.3",
     "validator": "^13.12.0"
   },
   "devDependencies": {
diff --git a/extensions/paste-as-plain-text/src/utils/paste-as-utils.ts b/extensions/paste-as-plain-text/src/utils/paste-as-utils.ts
index ef416a8f2e9..a8455f090fb 100644
--- a/extensions/paste-as-plain-text/src/utils/paste-as-utils.ts
+++ b/extensions/paste-as-plain-text/src/utils/paste-as-utils.ts
@@ -1,8 +1,9 @@
 import { Clipboard, closeMainWindow, Toast, updateCommandMetadata } from "@raycast/api";
 import { extractNumber, extractUrl, fetchTitle, isEmpty, showCustomHUD, transform } from "./common-utils";
 import { autoFetchTitle, PasteFormat, replaceClipboard } from "../types/types";
-import { isJSON, isURL } from "validator";
+import { isURL } from "validator";
 import fse from "fs-extra";
+import JSON5 from "json5";
 import { fileURLToPath } from "node:url";
 
 export async function pasteAs(advancedPasteFormat: string) {
@@ -24,11 +25,16 @@ export async function pasteAs(advancedPasteFormat: string) {
     }
     case PasteFormat.JSON: {
       // paste as json
-      if (isJSON(pasteStr)) {
-        pasteStr = JSON.stringify(JSON.parse(pasteStr), null, 2);
-        realPasteFormatIcon = "📦";
-        realPasteFormat = PasteFormat.JSON;
+      let objType;
+      try {
+        objType = JSON5.parse(pasteStr);
+      } catch (e) {
+        console.log("Invalid object type:", e);
+        break;
       }
+      pasteStr = JSON.stringify(objType, null, 2);
+      realPasteFormatIcon = "📦";
+      realPasteFormat = PasteFormat.JSON;
       break;
     }
     case PasteFormat.URL: {


Reviews:
user: login: greptile-apps[bot]
body: 
## PR Summary

This PR updates the Paste as Plain Text extension to support more flexible JSON-like formats using JSON5 instead of strict JSON parsing.

- Added JSON5 dependency in `package.json` to support JavaScript-style object notation with unquoted keys, single quotes, and trailing commas
- Modified `paste-as-utils.ts` to replace strict JSON validation with `JSON5.parse` in a try-catch block
- Added a new changelog entry correctly using the `{PR_MERGE_DATE}` placeholder format
- Added standard `.gitignore` file to prevent unnecessary files from being committed
- Added new contributor "kero13" to the extension's package.json

<sub>💡 (2/5) Greptile learns from your feedback when you react with 👍/👎!</sub>

<sub>4 file(s) reviewed, 2 comment(s)</sub>
<sub>[Edit PR Review Bot Settings](https://app.greptile.com/review/github) | [Greptile](https://greptile.com?utm_source=greptile_expert&utm_medium=github&utm_campaign=code_reviews&utm_content=extensions_18574)</sub>
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T08:44:05Z
user: login: pernielsentikaer
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-15T05:49:44Z

Review comments:
diff_hunk: @@ -24,11 +25,16 @@ export async function pasteAs(advancedPasteFormat: string) {
     }
     case PasteFormat.JSON: {
       // paste as json
-      if (isJSON(pasteStr)) {
-        pasteStr = JSON.stringify(JSON.parse(pasteStr), null, 2);
-        realPasteFormatIcon = "📦";
-        realPasteFormat = PasteFormat.JSON;
+      let objType;
+      try {
+        objType = JSON5.parse(pasteStr);
+      } catch (e) {
+        console.log("Invalid object type:", e);
+        break;
path: extensions/paste-as-plain-text/src/utils/paste-as-utils.ts
user: login: greptile-apps[bot]
body: style: Consider using showFailureToast from @raycast/utils instead of just logging to console when JSON parsing fails.

```suggestion
        showFailureToast(e, { title: "Could not parse JSON" });
        break;
```
created_at: 2025-04-14T08:43:08Z
author_association: CONTRIBUTOR

PR comments:
user: login: raycastbot
created_at: 2025-04-14T07:50:38Z
body: Thank you for your  contribution! :tada:

🔔 @koinzhang @pantajoe you might want to have a look.

You can use [this guide](https://developers.raycast.com/basics/review-pullrequest) to learn how to check out the Pull Request locally in order to test it.

You can expect an initial review within five business days.
author_association: COLLABORATOR
user: login: pernielsentikaer
created_at: 2025-04-14T12:35:24Z
body: Hi @kero13ro👋 

Thanks for your contribution 🔥

@koinzhang do you want to check this?
author_association: COLLABORATOR
user: login: koinzhang
created_at: 2025-04-14T12:48:15Z
body: Reviewed code, no issues.
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-04-15T05:51:57Z
body: <!-- add-pr-comment:add-pr-comment -->

**Published to the Raycast Store:**
https://raycast.com/koinzhang/paste-as-plain-text
author_association: CONTRIBUTOR
user: login: raycastbot
created_at: 2025-04-15T05:51:59Z
body: :tada: :tada: :tada:

We've rewarded your Raycast account with some credits. You will soon be able to exchange them for some swag.
author_association: COLLABORATOR