├── .editorconfig
├── .gitattributes
├── .github
└── FUNDING.yml
├── .gitignore
├── .husky
├── commit-msg
└── pre-commit
├── .lintstagedrc
├── .npmrc
├── .nvmrc
├── .release-it.json
├── .vscode-test.mjs
├── .vscode
├── extensions.json
├── launch.json
├── settings.json
└── tasks.json
├── .vscodeignore
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── assets
├── .gitkeep
└── logo.svg
├── biome.json
├── commitlint.config.js
├── icon.png
├── images
├── json-flow-1.gif
├── json-flow-2.gif
└── json-flow.png
├── index.html
├── l10n
├── bundle.l10n.de.json
├── bundle.l10n.es.json
├── bundle.l10n.fr.json
├── bundle.l10n.it.json
└── bundle.l10n.pt-br.json
├── package-lock.json
├── package.json
├── package.nls.de.json
├── package.nls.es.json
├── package.nls.fr.json
├── package.nls.it.json
├── package.nls.json
├── package.nls.pt-br.json
├── postcss.config.js
├── schemas
└── config.schema.json
├── src
├── app
│ ├── configs
│ │ ├── .gitkeep
│ │ ├── constants.config.ts
│ │ ├── extension.config.ts
│ │ └── index.ts
│ ├── controllers
│ │ ├── .gitkeep
│ │ ├── feedback.controller.ts
│ │ ├── files.controller.ts
│ │ ├── index.ts
│ │ ├── json.controller.ts
│ │ └── transform.controller.ts
│ ├── helpers
│ │ ├── .gitkeep
│ │ ├── index.ts
│ │ ├── json.helper.ts
│ │ ├── security.helper.ts
│ │ └── tree.helper.ts
│ ├── interfaces
│ │ ├── index.ts
│ │ └── tree.interface.ts
│ ├── models
│ │ ├── .gitkeep
│ │ ├── index.ts
│ │ └── node.model.ts
│ └── providers
│ │ ├── .gitkeep
│ │ ├── feedback.provider.ts
│ │ ├── files.providers.ts
│ │ ├── index.ts
│ │ └── json.provider.ts
├── extension.ts
└── test
│ └── extension.test.ts
├── tailwind.config.js
├── tsconfig.doc.json
├── tsconfig.json
├── tsconfig.node.json
├── tsconfig.web.json
├── vite.config.ts
├── vsc-extension-quickstart.md
└── webview
├── App.tsx
├── common.ts
├── components
├── CustomNode.tsx
├── Loading.css
├── Loading.tsx
└── layout-elements.ts
├── index.css
├── main.tsx
├── tsconfig.json
├── types
└── global.d.ts
└── vite-env.d.ts
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: https://EditorConfig.org
2 |
3 | # top-most EditorConfig file
4 | root = true
5 |
6 | [*.ts]
7 | charset = utf-8
8 | end_of_line = lf
9 | indent_size = 2
10 | indent_style = space
11 | quote_type = single
12 | spaces_around_brackets = inside
13 | trim_trailing_whitespace = true
14 |
15 | [*.md]
16 | max_line_length = off
17 | trim_trailing_whitespace = true
18 |
19 | [*.json]
20 | indent_size = 4
21 | indent_style = tab
22 | trim_trailing_whitespace = true
23 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # prettier v2 dictates LF
2 | # https://prettier.io/docs/en/options.html#end-of-line
3 | * text=auto eol=lf
4 |
5 | .vscode/*.json linguist-language=jsonc
6 | tslint.json linguist-language=jsonc
7 | tsconfig.json linguist-language=jsonc
8 | tsconfig.*.json linguist-language=jsonc
9 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: [ManuelGil]
4 | ko_fi: ManuelGil
5 | custom:
6 | ['https://paypal.me/ManuelFGil', 'https://www.buymeacoffee.com/ManuelGil']
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode-test/
2 | *.vsix
3 | compodoc/
4 | dist
5 | node_modules
6 | out
7 |
8 | # Logs
9 | logs
10 | *.log
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 | pnpm-debug.log*
15 | lerna-debug.log*
16 |
17 | node_modules
18 | dist
19 | dist-ssr
20 | *.local
21 |
22 | # Editor directories and files
23 | .vscode/*
24 | !.vscode/extensions.json
25 | .idea
26 | .DS_Store
27 | *.suo
28 | *.ntvs*
29 | *.njsproj
30 | *.sln
31 | *.sw?
--------------------------------------------------------------------------------
/.husky/commit-msg:
--------------------------------------------------------------------------------
1 | npx --no -- commitlint --edit ${1}
2 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | npx lint-staged
2 |
--------------------------------------------------------------------------------
/.lintstagedrc:
--------------------------------------------------------------------------------
1 | {
2 | "./**/*.ts": [
3 | "biome format --write",
4 | "biome lint --write",
5 | "git add ."
6 | ]
7 | }
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | package-lock=false
2 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | v22.10.0
2 |
--------------------------------------------------------------------------------
/.release-it.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://unpkg.com/release-it/schema/release-it.json",
3 | "git": {
4 | "commitMessage": "chore: :bookmark: release ${version}"
5 | },
6 | "github": {
7 | "release": true
8 | },
9 | "npm": {
10 | "publish": false
11 | },
12 | "plugins": {
13 | "@release-it/keep-a-changelog": {
14 | "filename": "CHANGELOG.md"
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/.vscode-test.mjs:
--------------------------------------------------------------------------------
1 | import { defineConfig } from '@vscode/test-cli';
2 |
3 | export default defineConfig({
4 | files: 'out/test/**/*.test.js',
5 | });
6 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | // See http://go.microsoft.com/fwlink/?LinkId=827846
3 | // for the documentation about the extensions.json format
4 | "recommendations": [
5 | "biomejs.biome",
6 | "shardulm94.trailing-spaces",
7 | "editorconfig.editorconfig",
8 | "usernamehw.errorlens",
9 | "kisstkondoros.vscode-gutter-preview"
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | // A launch configuration that compiles the extension and then opens it inside a new window
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | {
6 | "version": "0.2.0",
7 | "configurations": [
8 | {
9 | "name": "Run Extension",
10 | "type": "extensionHost",
11 | "request": "launch",
12 | "args": [
13 | "--extensionDevelopmentPath=${workspaceFolder}"
14 | ],
15 | "outFiles": [
16 | "${workspaceFolder}/out/**/*.js"
17 | ],
18 | "preLaunchTask": "${defaultBuildTask}"
19 | },
20 | {
21 | "name": "Extension Tests",
22 | "type": "extensionHost",
23 | "request": "launch",
24 | "args": [
25 | "--extensionDevelopmentPath=${workspaceFolder}",
26 | "--extensionTestsPath=${workspaceFolder}/out/test/suite/index"
27 | ],
28 | "outFiles": [
29 | "${workspaceFolder}/out/test/**/*.js"
30 | ],
31 | "preLaunchTask": "${defaultBuildTask}"
32 | }
33 | ]
34 | }
35 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | // Place your settings in this file to overwrite default and user settings.
2 | {
3 | "files.exclude": {
4 | "out": false // set this to true to hide the "out" folder with the compiled JS files
5 | },
6 | "search.exclude": {
7 | "out": true // set this to false to include "out" folder in search results
8 | },
9 | // Turn off tsc task auto detection since we have the necessary tasks as npm scripts
10 | "typescript.tsc.autoDetect": "off",
11 | "[typescript]": {
12 | "editor.defaultFormatter": "biomejs.biome"
13 | },
14 | "[javascript]": {
15 | "editor.defaultFormatter": "biomejs.biome"
16 | },
17 | "[typescriptreact]": {
18 | "editor.defaultFormatter": "biomejs.biome"
19 | },
20 | "[javascriptreact]": {
21 | "editor.defaultFormatter": "biomejs.biome"
22 | },
23 | "[html]": {
24 | "editor.defaultFormatter": "biomejs.biome"
25 | },
26 | "[css]": {
27 | "editor.defaultFormatter": "biomejs.biome"
28 | }
29 | }
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | // See https://go.microsoft.com/fwlink/?LinkId=733558
2 | // for the documentation about the tasks.json format
3 | {
4 | "version": "2.0.0",
5 | "tasks": [
6 | {
7 | "type": "npm",
8 | "script": "watch",
9 | "problemMatcher": "$tsc-watch",
10 | "isBackground": true,
11 | "presentation": {
12 | "reveal": "never"
13 | },
14 | "group": {
15 | "kind": "build",
16 | "isDefault": true
17 | }
18 | }
19 | ]
20 | }
21 |
--------------------------------------------------------------------------------
/.vscodeignore:
--------------------------------------------------------------------------------
1 | .editorconfig
2 | .gitattributes
3 | .gitignore
4 | .husky/**
5 | .lintstagedrc
6 | .vscode-test/**
7 | .vscode/**
8 | .yarnrc
9 | **/.vscode-test.*
10 | **/*.map
11 | **/*.ts
12 | **/eslint.config.mjs
13 | **/tsconfig.*.json
14 | **/tsconfig.json
15 | biome.json
16 | commitlint.config.js
17 | compodoc/**
18 | dist/**
19 | docs/**
20 | out/test/**
21 | src/**
22 | vsc-extension-quickstart.md
23 | webview/**
24 | yarn.lock
25 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to the "JSON Flow" extension will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 |
8 | ## [1.13.0] - 2025-01-16
9 |
10 | * feat: add error messages for cancelled operations in controllers ([ee5787a](https://github.com/ManuelGil/vscode-json-flow/commit/ee5787a))
11 |
12 | ## [1.12.0] - 2025-01-15
13 |
14 | * chore: :bookmark: release 1.12.0 ([dbd5ed2](https://github.com/ManuelGil/vscode-json-flow/commit/dbd5ed2))
15 | * chore: :bookmark: update release-it configuration and change changelog plugin ([18e2171](https://github.com/ManuelGil/vscode-json-flow/commit/18e2171))
16 | * chore: 🔧 configure automated github releases with release-it ([a17b8f6](https://github.com/ManuelGil/vscode-json-flow/commit/a17b8f6))
17 | * docs: add code generation section to README with supported languages and usage instructions ([d5dc9fe](https://github.com/ManuelGil/vscode-json-flow/commit/d5dc9fe))
18 | * docs: enhance README with code generation instructions and localization updates ([f2af773](https://github.com/ManuelGil/vscode-json-flow/commit/f2af773))
19 | * docs: update changelog format and add notable changes for recent features ([848f3f2](https://github.com/ManuelGil/vscode-json-flow/commit/848f3f2))
20 | * docs: update changelog with notable changes and version history ([c94ee59](https://github.com/ManuelGil/vscode-json-flow/commit/c94ee59))
21 | * docs: update localization files with new prompts for type or structure generation ([3abede5](https://github.com/ManuelGil/vscode-json-flow/commit/3abede5))
22 | * feat: ✨ add transform controller and enhance localization for conversion features ([7b01a65](https://github.com/ManuelGil/vscode-json-flow/commit/7b01a65))
23 | * feat: add release it changelog generation ([68b59d0](https://github.com/ManuelGil/vscode-json-flow/commit/68b59d0))
24 |
25 | ## [1.11.0] - 2025-01-09
26 |
27 | * feat: ✨ update VSCode version requirement, add test configuration, and enhance project structure ([ba8dfc7](https://github.com/ManuelGil/vscode-json-flow/commit/ba8dfc7))
28 |
29 | ## [1.10.0] - 2024-12-20
30 |
31 | * feat: ✨ add jsonFlow.enable configuration and enhance localization support ([fed5921](https://github.com/ManuelGil/vscode-json-flow/commit/fed5921))
32 |
33 | ## [1.9.0] - 2024-11-27
34 |
35 | * feat: ✨ add webview configuration and enhance layout element properties ([7b30d3c](https://github.com/ManuelGil/vscode-json-flow/commit/7b30d3c))
36 |
37 | ## [1.8.0] - 2024-11-24
38 |
39 | * feat: ✨ implement image saving functionality and enhance JSON controller ([3764e59](https://github.com/ManuelGil/vscode-json-flow/commit/3764e59))
40 |
41 | ## [1.7.0] - 2024-11-22
42 |
43 | * feat: ✨ add new JSON Flow commands and context menus ([612aad1](https://github.com/ManuelGil/vscode-json-flow/commit/612aad1))
44 |
45 | ## [1.6.0] - 2024-11-18
46 |
47 | * feat: ✨ update localization files and enhance file searching with fast-glob ([7139123](https://github.com/ManuelGil/vscode-json-flow/commit/7139123))
48 | * chore: :lipstick: updte cover image ([22b0c0d](https://github.com/ManuelGil/vscode-json-flow/commit/22b0c0d))
49 | * fix: 🐛 update exclusion patterns to replace hidden files with vendor directory in configuration ([11617d2](https://github.com/ManuelGil/vscode-json-flow/commit/11617d2))
50 |
51 | ## [1.5.0] - 2024-11-17
52 |
53 | * chore: 🔧 update version to 1.5.0 and enhance README with Product Hunt link and additional images ([70265aa](https://github.com/ManuelGil/vscode-json-flow/commit/70265aa))
54 | * feat: ✨ add layout direction configuration option and remove unused CSS ([c9ab641](https://github.com/ManuelGil/vscode-json-flow/commit/c9ab641))
55 | * feat: ✨ layout persist orientation state across views ([3bff5c6](https://github.com/ManuelGil/vscode-json-flow/commit/3bff5c6))
56 | * style: ✨ update CustomNode styling for improved layout and interaction ([a1c7ada](https://github.com/ManuelGil/vscode-json-flow/commit/a1c7ada))
57 | * style: ✨ update package description for clarity and improve code formatting in App.tsx ([0e24ede](https://github.com/ManuelGil/vscode-json-flow/commit/0e24ede))
58 | * refactor: ♻️ enhance type safety and improve layout node dimensions in tree helper and components ([43cc7ff](https://github.com/ManuelGil/vscode-json-flow/commit/43cc7ff))
59 |
60 | ## [1.4.0] - 2024-11-13
61 |
62 | * feat: :sparkles: add configuration option to show values in JSON graph ([8167e84](https://github.com/ManuelGil/vscode-json-flow/commit/8167e84))
63 | * feat: :sparkles: add tree interface and helper for JSON tree generation ([40c0c29](https://github.com/ManuelGil/vscode-json-flow/commit/40c0c29))
64 | * refactor: ♻️ improve type safety and effect handling ([e3de34e](https://github.com/ManuelGil/vscode-json-flow/commit/e3de34e))
65 | * refactor: ♻️ restructure tree generation logic and reintroduce type definitions ([52c67c2](https://github.com/ManuelGil/vscode-json-flow/commit/52c67c2))
66 | * style: ✨ enhance button styling and layout in webview ([965fce6](https://github.com/ManuelGil/vscode-json-flow/commit/965fce6))
67 | * add new layout ([80d8d4c](https://github.com/ManuelGil/vscode-json-flow/commit/80d8d4c))
68 |
69 | ## [1.3.1] - 2024-11-10
70 |
71 | * feat: :sparkles: add loading component and improve preview initialization delay ([d2d24e5](https://github.com/ManuelGil/vscode-json-flow/commit/d2d24e5))
72 | * feat: :sparkles: implement message handling for JSON updates in webview ([7827beb](https://github.com/ManuelGil/vscode-json-flow/commit/7827beb))
73 | * style: :art: add body padding and customize react-flow component styles ([752c965](https://github.com/ManuelGil/vscode-json-flow/commit/752c965))
74 | * style: :art: clean up code formatting and update package dependencies ([ad0bcee](https://github.com/ManuelGil/vscode-json-flow/commit/ad0bcee))
75 |
76 | ## [1.3.0] - 2024-11-08
77 |
78 | * refactor: :recycle: clean up configuration files and improve code formatting ([7564bfd](https://github.com/ManuelGil/vscode-json-flow/commit/7564bfd))
79 | * refactor: :recycle: remove unused helper functions and update package dependencies ([fab9138](https://github.com/ManuelGil/vscode-json-flow/commit/fab9138))
80 |
81 | ## [1.2.1] - 2024-11-08
82 |
83 | * fix: :adhesive_bandage: fix localization for feedback options and update package descriptions ([f395dfc](https://github.com/ManuelGil/vscode-json-flow/commit/f395dfc))
84 |
85 | ## [1.2.0] - 2024-11-08
86 |
87 | * feat: :sparkles: add localization support for German and Spanish languages ([634c871](https://github.com/ManuelGil/vscode-json-flow/commit/634c871))
88 | * refactor: :recycle: update JSON handling to use jsonc format and remove unused parser ([8752d5c](https://github.com/ManuelGil/vscode-json-flow/commit/8752d5c))
89 |
90 | ## [1.1.0] - 2024-11-07
91 |
92 | * feat: :sparkles: extend supported file types and enhance documentation for CSV and TSV formats ([c8ce799](https://github.com/ManuelGil/vscode-json-flow/commit/c8ce799))
93 |
94 | ## [1.0.1] - 2024-11-06
95 |
96 | * fix: :adhesive_bandage: enhance JSON handling by adding file type detection ([71abe2f](https://github.com/ManuelGil/vscode-json-flow/commit/71abe2f))
97 |
98 | ## [1.0.0-beta] - 2024-11-06
99 |
100 | * chore: :tada: initial commit ([945138b](https://github.com/ManuelGil/vscode-json-flow/commit/945138b))
101 | * chore: update contributors list in README.md ([0193af9](https://github.com/ManuelGil/vscode-json-flow/commit/0193af9))
102 | * chore: update extension description and keywords for improved clarity ([17ffafc](https://github.com/ManuelGil/vscode-json-flow/commit/17ffafc))
103 | * chore: update project configuration files ([7316a10](https://github.com/ManuelGil/vscode-json-flow/commit/7316a10))
104 | * feat: :sparkles: add convertToJson and copyContentAsJson methods ([2415393](https://github.com/ManuelGil/vscode-json-flow/commit/2415393))
105 | * feat: :sparkles: add copyContent command to JSON Manager ([23bb8a8](https://github.com/ManuelGil/vscode-json-flow/commit/23bb8a8))
106 | * feat: :sparkles: add getFileProperties command to JSON Manager ([17c884b](https://github.com/ManuelGil/vscode-json-flow/commit/17c884b))
107 | * feat: :sparkles: add react app ([65e0b2b](https://github.com/ManuelGil/vscode-json-flow/commit/65e0b2b))
108 | * feat: :sparkles: add support for JSON5 format in parsing logic and configuration ([26a70e0](https://github.com/ManuelGil/vscode-json-flow/commit/26a70e0))
109 | * feat: :sparkles: add support for multiple file types in JSON Flow and implement parsing logic ([886e15d](https://github.com/ManuelGil/vscode-json-flow/commit/886e15d))
110 | * feat: :sparkles: add webview ui toolkit ([8528830](https://github.com/ManuelGil/vscode-json-flow/commit/8528830))
111 | * feat: :sparkles: implement JsonController for handling JSON previews and commands ([4d1534d](https://github.com/ManuelGil/vscode-json-flow/commit/4d1534d))
112 | * feat: :sparkles: update files options to show a contextual menu ([963c477](https://github.com/ManuelGil/vscode-json-flow/commit/963c477))
113 | * feat: :sparkles: update JSONProvider to read JSON content from file ([f9fff41](https://github.com/ManuelGil/vscode-json-flow/commit/f9fff41))
114 | * feat: :technologist: improve react integration ([e6122c6](https://github.com/ManuelGil/vscode-json-flow/commit/e6122c6))
115 | * feat: add controls ([8a226dc](https://github.com/ManuelGil/vscode-json-flow/commit/8a226dc))
116 | * feat: add fixes ([181b39a](https://github.com/ManuelGil/vscode-json-flow/commit/181b39a))
117 | * feat: add react flow ([8dc0b4c](https://github.com/ManuelGil/vscode-json-flow/commit/8dc0b4c))
118 | * feat: add stylling ([51f25b7](https://github.com/ManuelGil/vscode-json-flow/commit/51f25b7))
119 | * feat: fix recurive function ([53c5dba](https://github.com/ManuelGil/vscode-json-flow/commit/53c5dba))
120 | * refactor: :fire: remove unused code in FilesController and JSONProvider ([976ba4c](https://github.com/ManuelGil/vscode-json-flow/commit/976ba4c))
121 | * refactor: :recycle: update JSON Provider to show a Webview Panel ([7151531](https://github.com/ManuelGil/vscode-json-flow/commit/7151531))
122 | * refactor: remove unused code and update JSONProvider to read JSON content from file ([f350cd0](https://github.com/ManuelGil/vscode-json-flow/commit/f350cd0))
123 | * refactor: rename extension from "JSON Manager" to "JSON Flow" and update related documentation ([8f60e06](https://github.com/ManuelGil/vscode-json-flow/commit/8f60e06))
124 | * build: :arrow_up: update dependencies and remove unused code ([9d25354](https://github.com/ManuelGil/vscode-json-flow/commit/9d25354))
125 | * build: add webview path ([960fb18](https://github.com/ManuelGil/vscode-json-flow/commit/960fb18))
126 | * fix: :rotating_light: fix compilation settings ([1ccbfa5](https://github.com/ManuelGil/vscode-json-flow/commit/1ccbfa5))
127 |
128 | [unreleased]: https://github.com/ManuelGil/vscode-json-flow/compare/v1.12.0...HEAD
129 | [1.12.0]: https://github.com/ManuelGil/vscode-json-flow/compare/v1.11.0...v1.12.0
130 | [1.11.0]: https://github.com/ManuelGil/vscode-json-flow/compare/v1.10.0...v1.11.0
131 | [1.10.0]: https://github.com/ManuelGil/vscode-json-flow/compare/v1.9.0...v1.10.0
132 | [1.9.0]: https://github.com/ManuelGil/vscode-json-flow/compare/v1.8.0...v1.9.0
133 | [1.8.0]: https://github.com/ManuelGil/vscode-json-flow/compare/v1.7.0...v1.8.0
134 | [1.7.0]: https://github.com/ManuelGil/vscode-json-flow/compare/v1.6.0...v1.7.0
135 | [1.6.0]: https://github.com/ManuelGil/vscode-json-flow/compare/v1.5.0...v1.6.0
136 | [1.5.0]: https://github.com/ManuelGil/vscode-json-flow/compare/v1.4.0...v1.5.0
137 | [1.4.0]: https://github.com/ManuelGil/vscode-json-flow/compare/v1.3.1...v1.4.0
138 | [1.3.1]: https://github.com/ManuelGil/vscode-json-flow/compare/v1.3.0...v1.3.1
139 | [1.3.0]: https://github.com/ManuelGil/vscode-json-flow/compare/v1.2.1...v1.3.0
140 | [1.2.1]: https://github.com/ManuelGil/vscode-json-flow/compare/v1.2.0...v1.2.1
141 | [1.2.0]: https://github.com/ManuelGil/vscode-json-flow/compare/v1.1.0...v1.2.0
142 | [1.1.0]: https://github.com/ManuelGil/vscode-json-flow/compare/v1.0.1...v1.1.0
143 | [1.0.1]: https://github.com/ManuelGil/vscode-json-flow/compare/v1.0.0-beta...v1.0.1
144 | [1.0.0-beta]: https://github.com/ManuelGil/vscode-json-flow/releases/tag/v1.0.0-beta
145 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | We as members, contributors, and leaders pledge to make participation in our
6 | community a harassment-free experience for everyone, regardless of age, body
7 | size, visible or invisible disability, ethnicity, sex characteristics, gender
8 | identity and expression, level of experience, education, socio-economic status,
9 | nationality, personal appearance, race, caste, color, religion, or sexual
10 | identity and orientation.
11 |
12 | We pledge to act and interact in ways that contribute to an open, welcoming,
13 | diverse, inclusive, and healthy community.
14 |
15 | ## Our Standards
16 |
17 | Examples of behavior that contributes to a positive environment for our
18 | community include:
19 |
20 | - Demonstrating empathy and kindness toward other people
21 | - Being respectful of differing opinions, viewpoints, and experiences
22 | - Giving and gracefully accepting constructive feedback
23 | - Accepting responsibility and apologizing to those affected by our mistakes,
24 | and learning from the experience
25 | - Focusing on what is best not just for us as individuals, but for the overall
26 | community
27 |
28 | Examples of unacceptable behavior include:
29 |
30 | - The use of sexualized language or imagery, and sexual attention or advances of
31 | any kind
32 | - Trolling, insulting or derogatory comments, and personal or political attacks
33 | - Public or private harassment
34 | - Publishing others' private information, such as a physical or email address,
35 | without their explicit permission
36 | - Other conduct which could reasonably be considered inappropriate in a
37 | professional setting
38 |
39 | ## Enforcement Responsibilities
40 |
41 | Community leaders are responsible for clarifying and enforcing our standards of
42 | acceptable behavior and will take appropriate and fair corrective action in
43 | response to any behavior that they deem inappropriate, threatening, offensive,
44 | or harmful.
45 |
46 | Community leaders have the right and responsibility to remove, edit, or reject
47 | comments, commits, code, wiki edits, issues, and other contributions that are
48 | not aligned to this Code of Conduct, and will communicate reasons for moderation
49 | decisions when appropriate.
50 |
51 | ## Scope
52 |
53 | This Code of Conduct applies within all community spaces, and also applies when
54 | an individual is officially representing the community in public spaces.
55 | Examples of representing our community include using an official e-mail address,
56 | posting via an official social media account, or acting as an appointed
57 | representative at an online or offline event.
58 |
59 | ## Enforcement
60 |
61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
62 | reported to the community leaders responsible for enforcement at
63 | [INSERT CONTACT METHOD].
64 | All complaints will be reviewed and investigated promptly and fairly.
65 |
66 | All community leaders are obligated to respect the privacy and security of the
67 | reporter of any incident.
68 |
69 | ## Enforcement Guidelines
70 |
71 | Community leaders will follow these Community Impact Guidelines in determining
72 | the consequences for any action they deem in violation of this Code of Conduct:
73 |
74 | ### 1. Correction
75 |
76 | **Community Impact**: Use of inappropriate language or other behavior deemed
77 | unprofessional or unwelcome in the community.
78 |
79 | **Consequence**: A private, written warning from community leaders, providing
80 | clarity around the nature of the violation and an explanation of why the
81 | behavior was inappropriate. A public apology may be requested.
82 |
83 | ### 2. Warning
84 |
85 | **Community Impact**: A violation through a single incident or series of
86 | actions.
87 |
88 | **Consequence**: A warning with consequences for continued behavior. No
89 | interaction with the people involved, including unsolicited interaction with
90 | those enforcing the Code of Conduct, for a specified period of time. This
91 | includes avoiding interactions in community spaces as well as external channels
92 | like social media. Violating these terms may lead to a temporary or permanent
93 | ban.
94 |
95 | ### 3. Temporary Ban
96 |
97 | **Community Impact**: A serious violation of community standards, including
98 | sustained inappropriate behavior.
99 |
100 | **Consequence**: A temporary ban from any sort of interaction or public
101 | communication with the community for a specified period of time. No public or
102 | private interaction with the people involved, including unsolicited interaction
103 | with those enforcing the Code of Conduct, is allowed during this period.
104 | Violating these terms may lead to a permanent ban.
105 |
106 | ### 4. Permanent Ban
107 |
108 | **Community Impact**: Demonstrating a pattern of violation of community
109 | standards, including sustained inappropriate behavior, harassment of an
110 | individual, or aggression toward or disparagement of classes of individuals.
111 |
112 | **Consequence**: A permanent ban from any sort of public interaction within the
113 | community.
114 |
115 | ## Attribution
116 |
117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118 | version 2.1, available at
119 | [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
120 |
121 | Community Impact Guidelines were inspired by
122 | [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
123 |
124 | For answers to common questions about this code of conduct, see the FAQ at
125 | [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
126 | [https://www.contributor-covenant.org/translations][translations].
127 |
128 | [homepage]: https://www.contributor-covenant.org
129 | [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
130 | [Mozilla CoC]: https://github.com/mozilla/diversity
131 | [FAQ]: https://www.contributor-covenant.org/faq
132 | [translations]: https://www.contributor-covenant.org/translations
133 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | When contributing to this repository, please first discuss the change you wish to make via issue,
4 | email, or any other method with the owners of this repository before making a change.
5 |
6 | Please note we have a code of conduct, please follow it in all your interactions with the project.
7 |
8 | ## Pull Request Process
9 |
10 | 1. Ensure any install or build dependencies are removed before the end of the layer when doing a
11 | build.
12 | 2. Update the README.md with details of changes to the interface, this includes new environment
13 | variables, exposed ports, useful file locations and container parameters.
14 | 3. Increase the version numbers in any examples files and the README.md to the new version that this
15 | Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/).
16 | 4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you
17 | do not have permission to do that, you may request the second reviewer to merge it for you.
18 |
19 | ## Code of Conduct
20 |
21 | ### Our Pledge
22 |
23 | In the interest of fostering an open and welcoming environment, we as
24 | contributors and maintainers pledge to making participation in our project and
25 | our community a harassment-free experience for everyone, regardless of age, body
26 | size, disability, ethnicity, gender identity and expression, level of experience,
27 | nationality, personal appearance, race, religion, or sexual identity and
28 | orientation.
29 |
30 | ### Our Standards
31 |
32 | Examples of behavior that contributes to creating a positive environment
33 | include:
34 |
35 | - Using welcoming and inclusive language
36 | - Being respectful of differing viewpoints and experiences
37 | - Gracefully accepting constructive criticism
38 | - Focusing on what is best for the community
39 | - Showing empathy towards other community members
40 |
41 | Examples of unacceptable behavior by participants include:
42 |
43 | - The use of sexualized language or imagery and unwelcome sexual attention or
44 | advances
45 | - Trolling, insulting/derogatory comments, and personal or political attacks
46 | - Public or private harassment
47 | - Publishing others' private information, such as a physical or electronic
48 | address, without explicit permission
49 | - Other conduct which could reasonably be considered inappropriate in a
50 | professional setting
51 |
52 | ### Our Responsibilities
53 |
54 | Project maintainers are responsible for clarifying the standards of acceptable
55 | behavior and are expected to take appropriate and fair corrective action in
56 | response to any instances of unacceptable behavior.
57 |
58 | Project maintainers have the right and responsibility to remove, edit, or
59 | reject comments, commits, code, wiki edits, issues, and other contributions
60 | that are not aligned to this Code of Conduct, or to ban temporarily or
61 | permanently any contributor for other behaviors that they deem inappropriate,
62 | threatening, offensive, or harmful.
63 |
64 | ### Scope
65 |
66 | This Code of Conduct applies both within project spaces and in public spaces
67 | when an individual is representing the project or its community. Examples of
68 | representing a project or community include using an official project e-mail
69 | address, posting via an official social media account, or acting as an appointed
70 | representative at an online or offline event. Representation of a project may be
71 | further defined and clarified by project maintainers.
72 |
73 | ### Enforcement
74 |
75 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
76 | reported by contacting the project team at [INSERT EMAIL ADDRESS]. All
77 | complaints will be reviewed and investigated and will result in a response that
78 | is deemed necessary and appropriate to the circumstances. The project team is
79 | obligated to maintain confidentiality with regard to the reporter of an incident.
80 | Further details of specific enforcement policies may be posted separately.
81 |
82 | Project maintainers who do not follow or enforce the Code of Conduct in good
83 | faith may face temporary or permanent repercussions as determined by other
84 | members of the project's leadership.
85 |
86 | ### Attribution
87 |
88 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
89 | available at [http://contributor-covenant.org/version/1/4][version]
90 |
91 | [homepage]: http://contributor-covenant.org
92 | [version]: http://contributor-covenant.org/version/1/4/
93 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Manuel Gil
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # JSON Flow
2 |
3 | [](https://marketplace.visualstudio.com/items?itemName=imgildev.vscode-json-flow)
4 | [](https://marketplace.visualstudio.com/items?itemName=imgildev.vscode-json-flow)
5 | [](https://marketplace.visualstudio.com/items?itemName=imgildev.vscode-json-flow)
6 | [](https://marketplace.visualstudio.com/items?itemName=imgildev.vscode-json-flow&ssr=false#review-details)
7 | [](https://github.com/ManuelGil/vscode-json-flow)
8 | [](https://github.com/ManuelGil/vscode-json-flow/blob/main/LICENSE)
9 |
10 | Transform your JSON files into interactive node-based graphs directly in Visual Studio Code. JSON Flow makes working with structured data effortless and visually intuitive, turning raw data into dynamic, interactive visualizations. Perfect for developers, analysts, and data enthusiasts who want to understand and navigate complex JSON structures with ease.
11 |
12 | [](https://marketplace.visualstudio.com/items?itemName=imgildev.vscode-json-flow)
13 |
14 | ## Table of Contents
15 |
16 | - [JSON Flow](#json-flow)
17 | - [Table of Contents](#table-of-contents)
18 | - [Requirements](#requirements)
19 | - [Features](#features)
20 | - [Interactive Data Visualization](#interactive-data-visualization)
21 | - [Enhanced JSON Management](#enhanced-json-management)
22 | - [Supported File Formats](#supported-file-formats)
23 | - [JSON Family](#json-family)
24 | - [YAML](#yaml)
25 | - [TOML](#toml)
26 | - [INI Format](#ini-format)
27 | - [Properties and Environment Files](#properties-and-environment-files)
28 | - [XML](#xml)
29 | - [CSV](#csv)
30 | - [TSV](#tsv)
31 | - [HCL](#hcl)
32 | - [File Explorer](#file-explorer)
33 | - [Usage](#usage)
34 | - [Project Settings](#project-settings)
35 | - [Code Generation from JSON](#code-generation-from-json)
36 | - [Supported Languages](#supported-languages)
37 | - [How to Use](#how-to-use)
38 | - [Example](#example)
39 | - [Development](#development)
40 | - [Getting Started](#getting-started)
41 | - [React Webview](#react-webview)
42 | - [Build](#build)
43 | - [Compile Webview](#compile-webview)
44 | - [VSXpert Template](#vsxpert-template)
45 | - [Other Extensions](#other-extensions)
46 | - [Contributing](#contributing)
47 | - [Code of Conduct](#code-of-conduct)
48 | - [Changelog](#changelog)
49 | - [Authors](#authors)
50 | - [License](#license)
51 |
52 | ## Requirements
53 |
54 | - VSCode 1.88.0 or later
55 |
56 | ## Features
57 |
58 | ### Interactive Data Visualization
59 |
60 | - **Node-Based Graphs**: Instantly visualize your JSON data as interactive node-based graphs, making complex structures easy to interpret and navigate.
61 | - **Dynamic Data Exploration**: Use zoom and navigation controls to explore your data in real-time, providing a seamless, intuitive way to dive into JSON structures.
62 |
63 | ### Enhanced JSON Management
64 |
65 | - **File Explorer**: Access and manage JSON files efficiently with the built-in file explorer, offering a range of organizational and file management tools.
66 | - **File Conversion**: Easily convert formats like YAML, TOML, INI, and others to JSON with a single click, streamlining your workflow and expanding compatibility.
67 | - **Show Selection as JSON**: Preview selected content in the JSON Flow view, simplifying data exploration and helping you make sense of your data at a glance.
68 | - **Copy Content to Clipboard**: Copy the content of the selected file to the clipboard, simplifying data sharing and integration with other tools.
69 | - **Copy Content as JSON**: Copy the content of the selected file as JSON, enabling seamless data transfer and integration with other applications.
70 | - **Get File Properties**: Quickly access the basic properties of the selected file, including path, language, and line count, streamlining file management and organization.
71 |
72 | ### Supported File Formats
73 |
74 | #### JSON Family
75 |
76 | - **`json`**: Standard JSON files for all your data needs.
77 | - **`jsonc`**: JSON with comments — great for configuration files that need explanations.
78 | - **`json5`**: A more relaxed JSON format, offering improved readability and flexibility.
79 |
80 | #### YAML
81 |
82 | - **`yaml`** & **`yml`**: Widely used for configuration files, CI/CD pipelines, cloud deployment settings, and more.
83 |
84 | #### TOML
85 |
86 | - **`toml`**: A user-friendly config file format, especially popular in Rust and other applications needing readability.
87 |
88 | #### INI Format
89 |
90 | - **`ini` & `cfg`**: Classic key-value format for app and system settings, widely used in software configurations.
91 |
92 | #### Properties and Environment Files
93 |
94 | - **`properties`**: Java-style configuration files, perfect for managing app settings.
95 | - **`env`**: Environment variable files commonly used for application configurations and secrets.
96 |
97 | #### XML
98 |
99 | - **`xml`**: A versatile, structured data format used in a variety of applications and document storage.
100 |
101 | #### CSV
102 |
103 | - **`csv`**: Comma-separated values, ideal for tabular data storage and exchange.
104 |
105 | #### TSV
106 |
107 | - **`tsv`**: Tab-separated values, another popular format for storing and sharing tabular data.
108 |
109 | #### HCL
110 |
111 | - **`hcl`**: HashiCorp Configuration Language, often used in DevOps tools like Terraform.
112 |
113 | ### File Explorer
114 |
115 | | Title | Purpose |
116 | | --- | --- |
117 | | Open File | Open the selected file |
118 | | Convert to JSON | Convert the selected file to JSON |
119 | | Convert to Type or Structure | Convert the selected file to a specific type or structure. See [Code Generation from JSON](#code-generation-from-json) for more details |
120 | | Copy Content to Clipboard | Copy the content of the selected file to the clipboard |
121 | | Copy Content as JSON | Copy the content of the selected file as JSON |
122 | | Get File Properties | Get the properties of the selected file |
123 | | Show Selection as JSON | Show the Selection in the JSON Flow view |
124 |
125 | ## Usage
126 |
127 | 1. Open a JSON file in Visual Studio Code.
128 |
129 | 2. Click on the JSON Flow icon in the top right corner of the editor.
130 |
131 | 3. The JSON Flow view will open, displaying your JSON data as an interactive node-based graph.
132 |
133 | 4. Click on the navigation buttons to zoom in and out, and explore your data in real-time.
134 |
135 | - **Zoom In**: Click on the `+` button to zoom in on the graph.
136 | - **Zoom Out**: Click on the `-` button to zoom out on the graph.
137 |
138 | 
139 |
140 | 
141 |
142 | ## Project Settings
143 |
144 | Configure your project by creating or updating a settings.json file at the project's root. If you already have a `.vscode/settings.json` file, skip the first two steps.
145 |
146 | 1. Open the command palette in VSCode:
147 |
148 | - `CTRL + SHIFT + P` (Windows)
149 | - `CMD + SHIFT + P` (Mac OS)
150 |
151 | 2. Type `Preferences: Open Workspace Settings (JSON)`.
152 |
153 | 3. In the `.vscode/settings.json` file, copy and paste the following settings:
154 |
155 | ```jsonc
156 | {
157 | "jsonFlow.enable": true, // Enable or disable the extension. Example: true, false
158 | "jsonFlow.files.include": [
159 | "json",
160 | "jsonc"
161 | ], // The file extensions to watch for changes. Example: "json", "jsonc"
162 | "jsonFlow.files.exclude": [
163 | "**/node_modules/**",
164 | "**/dist/**",
165 | "**/out/**",
166 | "**/build/**",
167 | "**/vendor/**"
168 | ], // The files to exclude from watching. Example: "**/node_modules/**", "**/dist/**", "**/out/**", "**/build/**", "**/vendor/**"
169 | "jsonFlow.files.showPath": true, // Show the path of the file in the file name. Example: "home.component.tsx (pages/home)"
170 | "jsonFlow.graph.showValues": true, // Show the values of the nodes in the graph. Example: "name: 'John Doe'"
171 | "jsonFlow.graph.nodeWidth": 200, // The width of the nodes in the graph. Example: 200
172 | "jsonFlow.graph.nodeHeight": 50, // The height of the nodes in the graph. Example: 50
173 | "jsonFlow.graph.nodeBorderColor": "white", // The border color of the nodes in the graph. Example: "white"
174 | "jsonFlow.graph.nodeColor": "white", // The color of the nodes in the graph. Example: "white"
175 | "jsonFlow.graph.edgeColor": "white", // The color of the edges in the graph. Example: "white"
176 | "jsonFlow.graph.layoutDirection": "TB", // The layout direction of the graph. Example: "TB", "LR"
177 | "jsonFlow.image.folder": "images", // The folder where the images will be saved. Example: "images"
178 | }
179 | ```
180 |
181 | 4. **Restart VS Code**
182 |
183 | Your project is now set up to automatically format code upon saving.
184 |
185 | ## Code Generation from JSON
186 |
187 | Enhance your development workflow by generating code from JSON structures in various programming languages using the [quicktype](https://www.npmjs.com/package/quicktype) library.
188 |
189 | ### Supported Languages
190 |
191 | - TypeScript
192 | - Go
193 | - Rust
194 | - Python
195 | - Java
196 | - C#
197 | - Swift
198 | - Kotlin
199 | - Dart
200 | - C++
201 | - Objective-C
202 | - PHP
203 | - Ruby
204 | - Scala
205 | - Elm
206 | - JSON Schema
207 | - Haskell
208 | - JavaScript
209 | - Flow
210 | - Prop-Types
211 | - Pike
212 |
213 | ### How to Use
214 |
215 | 1. **Open a JSON File**: Open the JSON file you wish to convert in Visual Studio Code.
216 |
217 | 2. **Right-Click on the Editor**:
218 | - Right-click on the editor to open the context menu.
219 | - Select the `Convert to Type or Structure` option.
220 |
221 | 3. **Select the Target Language**: Choose your desired programming language from the provided list.
222 |
223 | 4. **Provide a Type or Structure Name**: Enter a name for the class, structure, or interface that will represent the JSON data in the selected language.
224 |
225 | 5. **Review the Generated Code**: The extension will generate the corresponding code and display it in a new editor tab. You can review, copy, or save the code as needed.
226 |
227 | ### Example
228 |
229 | Given the following JSON:
230 |
231 | ```json
232 | {
233 | "name": "John Doe",
234 | "age": 30,
235 | "email": "john.doe@example.com"
236 | }
237 | ```
238 |
239 | If you select TypeScript as the target language and name the type Person, the generated code will be:
240 |
241 | ```typescript
242 | export interface Person {
243 | name: string;
244 | age: number;
245 | email: string;
246 | }
247 | ```
248 |
249 | This interface can be directly utilized in your TypeScript project to ensure proper type checking and IntelliSense support.
250 |
251 | ## Development
252 |
253 | For the development of this extension, you need to have Node.js installed on your machine. You can download it from the [official website](https://nodejs.org/).
254 |
255 | ### Getting Started
256 |
257 | 1. Clone the repository:
258 |
259 | ```bash
260 | git clone
261 | ```
262 |
263 | 2. Install the dependencies:
264 |
265 | ```bash
266 | npm install
267 | ```
268 |
269 | 3. Open the project in VSCode:
270 |
271 | ```bash
272 | code .
273 | ```
274 |
275 | 4. Press `F5` to open a new window with the extension loaded.
276 | 5. Make your changes in the `src` directory.
277 |
278 | ### React Webview
279 |
280 | To test the extension in a webview, run the following command:
281 |
282 | ```bash
283 | npm run dev
284 | ```
285 |
286 | This command will open a new window with the extension loaded.
287 |
288 | Make your changes in the `webview` directory.
289 |
290 | ## Build
291 |
292 | ### Compile Webview
293 |
294 | 1. Run the build command:
295 |
296 | ```bash
297 | npm run build
298 | ```
299 |
300 | 2. Run the compile command:
301 |
302 | ```bash
303 | npm run compile
304 | ```
305 |
306 | 3. The compiled files will be in the `out` directory.
307 | 4. Press `F5` to open a new window with the extension loaded.
308 |
309 | ## VSXpert Template
310 |
311 | This extension was created using [VSXpert](https://vsxpert.com), a template that helps you create Visual Studio Code extensions with ease. VSXpert provides a simple and easy-to-use structure to get you started quickly.
312 |
313 | ## Other Extensions
314 |
315 | - [Angular File Generator](https://marketplace.visualstudio.com/items?itemName=imgildev.vscode-angular-generator)
316 | - [NestJS File Generator](https://marketplace.visualstudio.com/items?itemName=imgildev.vscode-nestjs-generator)
317 | - [T3 Stack / NextJS / ReactJS File Generator](https://marketplace.visualstudio.com/items?itemName=imgildev.vscode-nextjs-generator)
318 | - [Auto Barrel](https://marketplace.visualstudio.com/items?itemName=imgildev.vscode-auto-barrel)
319 | - [CodeIgniter 4 Spark](https://marketplace.visualstudio.com/items?itemName=imgildev.vscode-codeigniter4-spark)
320 |
321 | ## Contributing
322 |
323 | Please read [CONTRIBUTING.md](./CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests to us.
324 |
325 | ## Code of Conduct
326 |
327 | Please read [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md) for details on our code of conduct.
328 |
329 | ## Changelog
330 |
331 | See [CHANGELOG.md](./CHANGELOG.md)
332 |
333 | ## Authors
334 |
335 | - **Manuel Gil** - _Owner_ - [ManuelGil](https://github.com/ManuelGil)
336 | - **Santiago Rey** - _Collaborator_ - [ksreyr](https://github.com/ksreyr)
337 | - **Andry Orellana** - _Collaborator_ - [AndryOre](https://github.com/AndryOre)
338 |
339 | See also the list of [contributors](https://github.com/ManuelGil/vscode-json-flow/contributors) who participated in this project.
340 |
341 | ## License
342 |
343 | JSON Flow is licensed under the MIT License - see the [MIT License](https://opensource.org/licenses/MIT) for details.
344 |
--------------------------------------------------------------------------------
/assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelGil/vscode-json-flow/d6515cd6b0259e893793e999deafcef49df6082f/assets/.gitkeep
--------------------------------------------------------------------------------
/assets/logo.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/biome.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
3 | "vcs": { "enabled": false, "clientKind": "git", "useIgnoreFile": false },
4 | "files": {
5 | "include": ["src/**/*.ts", "webview/**/*.ts", "webview/**/*.tsx"],
6 | "ignoreUnknown": false,
7 | "ignore": []
8 | },
9 | "formatter": {
10 | "enabled": true,
11 | "useEditorconfig": true,
12 | "formatWithErrors": false,
13 | "indentStyle": "space",
14 | "indentWidth": 2,
15 | "lineEnding": "lf",
16 | "lineWidth": 80,
17 | "attributePosition": "auto",
18 | "bracketSpacing": true,
19 | "ignore": [
20 | "./.vscode",
21 | "./compodoc",
22 | "./coverage",
23 | "./dist",
24 | "./docs",
25 | "./node_modules",
26 | "./out",
27 | "./tests",
28 | "**/commitlint.config.js"
29 | ]
30 | },
31 | "organizeImports": { "enabled": true },
32 | "linter": {
33 | "enabled": true,
34 | "rules": {
35 | "recommended": false,
36 | "complexity": {
37 | "noBannedTypes": "error",
38 | "noExtraBooleanCast": "error",
39 | "noMultipleSpacesInRegularExpressionLiterals": "error",
40 | "noUselessCatch": "error",
41 | "noUselessThisAlias": "error",
42 | "noUselessTypeConstraint": "error",
43 | "noWith": "error"
44 | },
45 | "correctness": {
46 | "noConstAssign": "error",
47 | "noConstantCondition": "error",
48 | "noEmptyCharacterClassInRegex": "error",
49 | "noEmptyPattern": "error",
50 | "noGlobalObjectCalls": "error",
51 | "noInnerDeclarations": "error",
52 | "noInvalidBuiltinInstantiation": "error",
53 | "noInvalidConstructorSuper": "error",
54 | "noNewSymbol": "error",
55 | "noNonoctalDecimalEscape": "error",
56 | "noPrecisionLoss": "error",
57 | "noSelfAssign": "error",
58 | "noSetterReturn": "error",
59 | "noSwitchDeclarations": "error",
60 | "noUndeclaredVariables": "error",
61 | "noUnreachable": "error",
62 | "noUnreachableSuper": "error",
63 | "noUnsafeFinally": "error",
64 | "noUnsafeOptionalChaining": "error",
65 | "noUnusedLabels": "error",
66 | "noUnusedPrivateClassMembers": "error",
67 | "noUnusedVariables": "error",
68 | "useArrayLiterals": "off",
69 | "useExhaustiveDependencies": "warn",
70 | "useHookAtTopLevel": "error",
71 | "useIsNan": "error",
72 | "useValidForDirection": "error",
73 | "useYield": "error"
74 | },
75 | "style": {
76 | "noNamespace": "error",
77 | "useAsConstAssertion": "error",
78 | "useBlockStatements": "warn",
79 | "useNamingConvention": {
80 | "level": "warn",
81 | "options": { "strictCase": false }
82 | },
83 | "useThrowOnlyError": "warn"
84 | },
85 | "suspicious": {
86 | "noAssignInExpressions": "error",
87 | "noAsyncPromiseExecutor": "error",
88 | "noCatchAssign": "error",
89 | "noClassAssign": "error",
90 | "noCompareNegZero": "error",
91 | "noControlCharactersInRegex": "error",
92 | "noDebugger": "error",
93 | "noDoubleEquals": "warn",
94 | "noDuplicateCase": "error",
95 | "noDuplicateClassMembers": "error",
96 | "noDuplicateObjectKeys": "error",
97 | "noDuplicateParameters": "error",
98 | "noEmptyBlockStatements": "error",
99 | "noExplicitAny": "error",
100 | "noExtraNonNullAssertion": "error",
101 | "noFallthroughSwitchClause": "error",
102 | "noFunctionAssign": "error",
103 | "noGlobalAssign": "error",
104 | "noImportAssign": "error",
105 | "noMisleadingCharacterClass": "error",
106 | "noMisleadingInstantiator": "error",
107 | "noPrototypeBuiltins": "error",
108 | "noRedeclare": "error",
109 | "noShadowRestrictedNames": "error",
110 | "noSparseArray": "error",
111 | "noUnsafeDeclarationMerging": "error",
112 | "noUnsafeNegation": "error",
113 | "useGetterReturn": "error",
114 | "useNamespaceKeyword": "error",
115 | "useValidTypeof": "error"
116 | }
117 | },
118 | "ignore": [
119 | "**/node_modules",
120 | "**/dist",
121 | "**/out",
122 | "**/*.d.ts",
123 | "**/vite.config.ts",
124 | "**/webview",
125 | "**/.vscode/",
126 | "**/compodoc/",
127 | "**/coverage/",
128 | "**/dist/",
129 | "**/docs/",
130 | "**/node_modules/",
131 | "**/out/",
132 | "**/tests/",
133 | "**/commitlint.config.js"
134 | ]
135 | },
136 | "javascript": {
137 | "formatter": {
138 | "jsxQuoteStyle": "double",
139 | "quoteProperties": "preserve",
140 | "trailingCommas": "all",
141 | "semicolons": "always",
142 | "arrowParentheses": "always",
143 | "bracketSameLine": false,
144 | "quoteStyle": "single",
145 | "attributePosition": "auto",
146 | "bracketSpacing": true
147 | }
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/commitlint.config.js:
--------------------------------------------------------------------------------
1 | module.exports = { extends: ['@commitlint/config-conventional'] };
2 |
--------------------------------------------------------------------------------
/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelGil/vscode-json-flow/d6515cd6b0259e893793e999deafcef49df6082f/icon.png
--------------------------------------------------------------------------------
/images/json-flow-1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelGil/vscode-json-flow/d6515cd6b0259e893793e999deafcef49df6082f/images/json-flow-1.gif
--------------------------------------------------------------------------------
/images/json-flow-2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelGil/vscode-json-flow/d6515cd6b0259e893793e999deafcef49df6082f/images/json-flow-2.gif
--------------------------------------------------------------------------------
/images/json-flow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelGil/vscode-json-flow/d6515cd6b0259e893793e999deafcef49df6082f/images/json-flow.png
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | JSON Preview
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/l10n/bundle.l10n.de.json:
--------------------------------------------------------------------------------
1 | {
2 | "No workspace folders are open. Please open a workspace folder to use this extension": "Keine Arbeitsbereichsordner sind geöffnet. Bitte öffnen Sie einen Arbeitsbereichsordner, um diese Erweiterung zu verwenden",
3 | "Select a workspace folder to use. This folder will be used to load workspace-specific configuration for the extension": "Wählen Sie einen Arbeitsbereichsordner aus, der verwendet werden soll. Dieser Ordner wird verwendet, um arbeitsbereichsspezifische Konfigurationen für die Erweiterung zu laden",
4 | "{0} is now enabled and ready to use": "{0} ist jetzt aktiviert und einsatzbereit",
5 | "{0} is now disabled": "{0} ist jetzt deaktiviert",
6 | "{0} is disabled in settings. Enable it to use its features": "{0} ist in den Einstellungen deaktiviert. Aktivieren Sie es, um seine Funktionen zu verwenden",
7 | "Welcome to {0} version {1}! The extension is now active": "Willkommen bei {0} Version {1}! Die Erweiterung ist jetzt aktiv",
8 | "New version of {0} is available. Check out the release notes for version {1}": "Eine neue Version von {0} ist verfügbar. Überprüfen Sie die Versionshinweise für Version {1}",
9 | "Release Notes": "Versionshinweise",
10 | "Dismiss": "Verwerfen",
11 | "No active editor!": "Kein aktiver Editor!",
12 | "No selection!": "Keine Auswahl!",
13 | "Operation cancelled!": "Vorgang abgebrochen!",
14 | "Error while finding files: {0}": "Fehler beim Suchen von Dateien: {0}",
15 | "Invalid file type!": "Ungültiger Dateityp!",
16 | "Error parsing {0}: {1}": "Fehler beim Parsen von {0}: {1}",
17 | "Content copied to clipboard": "Inhalt in die Zwischenablage kopiert",
18 | "Content copied as JSON to clipboard": "Inhalt als JSON in die Zwischenablage kopiert",
19 | "File Name: {0}\nLanguage: {1}\nLines: {2}\nVersion: {3}": "Dateiname: {0}\nSprache: {1}\nZeilen: {2}\nVersion: {3}",
20 | "Report Issues": "Probleme melden",
21 | "Rate Us": "Bewerten Sie uns",
22 | "No workspace folder available to save the image!": "Kein Arbeitsbereichsordner verfügbar, um das Bild zu speichern!",
23 | "Select a workspace folder to save the image": "Wählen Sie einen Arbeitsbereichsordner aus, um das Bild zu speichern",
24 | "Image saved to: {0}": "Bild gespeichert unter: {0}",
25 | "Enter the name of the type or structure generated": "Geben Sie den Namen des generierten Typs oder der Struktur ein",
26 | "Enter the name of the type or structure, e.g., User, Post, etc.": "Geben Sie den Namen des Typs oder der Struktur ein, z. B. Benutzer, Beitrag usw.",
27 | "The name of the type or structure is required!": "Der Name des Typs oder der Struktur ist erforderlich!"
28 | }
29 |
--------------------------------------------------------------------------------
/l10n/bundle.l10n.es.json:
--------------------------------------------------------------------------------
1 | {
2 | "No workspace folders are open. Please open a workspace folder to use this extension": "No hay carpetas de espacio de trabajo abiertas. Abra una carpeta de espacio de trabajo para usar esta extensión",
3 | "Select a workspace folder to use. This folder will be used to load workspace-specific configuration for the extension": "Seleccione una carpeta de espacio de trabajo para usar. Esta carpeta se utilizará para cargar la configuración específica del espacio de trabajo para la extensión",
4 | "{0} is now enabled and ready to use": "{0} está ahora habilitado y listo para usar",
5 | "{0} is now disabled": "{0} está ahora deshabilitado",
6 | "{0} is disabled in settings. Enable it to use its features": "{0} está deshabilitado en la configuración. Habilítelo para usar sus funciones",
7 | "Welcome to {0} version {1}! The extension is now active": "¡Bienvenido a {0} versión {1}! La extensión ahora está activa",
8 | "New version of {0} is available. Check out the release notes for version {1}": "Hay disponible una nueva versión de {0}. Consulte las notas de la versión {1}",
9 | "Release Notes": "Notas de la versión",
10 | "Dismiss": "Descartar",
11 | "No active editor!": "¡No hay editor activo!",
12 | "No selection!": "¡No hay selección!",
13 | "Operation cancelled!": "¡Operación cancelada!",
14 | "Error while finding files: {0}": "Error al buscar archivos: {0}",
15 | "Invalid file type!": "¡Tipo de archivo no válido!",
16 | "Error parsing {0}: {1}": "Error al parsear {0}: {1}",
17 | "Content copied to clipboard": "Contenido copiado al portapapeles",
18 | "Content copied as JSON to clipboard": "Contenido copiado como JSON al portapapeles",
19 | "File Name: {0}\nLanguage: {1}\nLines: {2}\nVersion: {3}": "Nombre de archivo: {0}\nIdioma: {1}\nLíneas: {2}\nVersión: {3}",
20 | "Report Issues": "Reportar problemas",
21 | "Rate Us": "Califícanos",
22 | "No workspace folder available to save the image!": "¡No hay carpeta de espacio de trabajo disponible para guardar la imagen!",
23 | "Select a workspace folder to save the image": "Seleccione una carpeta de espacio de trabajo para guardar la imagen",
24 | "Image saved to: {0}": "Imagen guardada en: {0}",
25 | "Enter the name of the type or structure generated": "Introduzca el nombre del tipo o estructura generada",
26 | "Enter the name of the type or structure, e.g., User, Post, etc.": "Introduzca el nombre del tipo o estructura, por ejemplo, Usuario, Publicación, etc.",
27 | "The name of the type or structure is required!": "¡Se requiere el nombre del tipo o estructura!"
28 | }
29 |
--------------------------------------------------------------------------------
/l10n/bundle.l10n.fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "No workspace folders are open. Please open a workspace folder to use this extension": "Aucun dossier d'espace de travail n'est ouvert. Veuillez ouvrir un dossier d'espace de travail pour utiliser cette extension",
3 | "Select a workspace folder to use. This folder will be used to load workspace-specific configuration for the extension": "Sélectionnez un dossier d'espace de travail à utiliser. Ce dossier sera utilisé pour charger la configuration spécifique à l'espace de travail pour l'extension",
4 | "{0} is now enabled and ready to use": "{0} est maintenant activé et prêt à être utilisé",
5 | "{0} is now disabled": "{0} est maintenant désactivé",
6 | "{0} is disabled in settings. Enable it to use its features": "{0} est désactivé dans les paramètres. Activez-le pour utiliser ses fonctionnalités",
7 | "Welcome to {0} version {1}! The extension is now active": "Bienvenue dans la version {0} {1} ! L'extension est maintenant active",
8 | "New version of {0} is available. Check out the release notes for version {1}": "Une nouvelle version de {0} est disponible. Consultez les notes de version pour la version {1}",
9 | "Release Notes": "Notes de version",
10 | "Dismiss": "Rejeter",
11 | "No active editor!": "Aucun éditeur actif!",
12 | "No selection!": "Aucune sélection!",
13 | "Operation cancelled!": "Opération annulée!",
14 | "Error while finding files: {0}": "Erreur lors de la recherche des fichiers : {0}",
15 | "Invalid file type!": "Type de fichier non valide!",
16 | "Error parsing {0}: {1}": "Erreur d'analyse de {0} : {1}",
17 | "Content copied to clipboard": "Contenu copié dans le presse-papiers",
18 | "Content copied as JSON to clipboard": "Contenu copié en tant que JSON dans le presse-papiers",
19 | "File Name: {0}\nLanguage: {1}\nLines: {2}\nVersion: {3}": "Nom du fichier : {0}\nLangue : {1}\nLignes : {2}\nVersion : {3}",
20 | "Report Issues": "Signaler des problèmes",
21 | "Rate Us": "Évaluez-nous",
22 | "No workspace folder available to save the image!": "Aucun dossier d'espace de travail disponible pour enregistrer l'image!",
23 | "Select a workspace folder to save the image": "Sélectionnez un dossier d'espace de travail pour enregistrer l'image",
24 | "Image saved to: {0}": "Image enregistrée sous : {0}",
25 | "Enter the name of the type or structure generated": "Entrez le nom du type ou de la structure généré",
26 | "Enter the name of the type or structure, e.g., User, Post, etc.": "Entrez le nom du type ou de la structure, par exemple, Utilisateur, Post, etc.",
27 | "The name of the type or structure is required!": "Le nom du type ou de la structure est requis!"
28 | }
29 |
--------------------------------------------------------------------------------
/l10n/bundle.l10n.it.json:
--------------------------------------------------------------------------------
1 | {
2 | "No workspace folders are open. Please open a workspace folder to use this extension": "Nessuna cartella dello spazio di lavoro è aperta. Apri una cartella dello spazio di lavoro per utilizzare questa estensione",
3 | "Select a workspace folder to use. This folder will be used to load workspace-specific configuration for the extension": "Seleziona una cartella dello spazio di lavoro da utilizzare. Questa cartella verrà utilizzata per caricare la configurazione specifica dello spazio di lavoro per l'estensione",
4 | "{0} is now enabled and ready to use": "{0} è ora abilitato e pronto per l'uso",
5 | "{0} is now disabled": "{0} è ora disabilitato",
6 | "{0} is disabled in settings. Enable it to use its features": "{0} è disabilitato nelle impostazioni. Abilitalo per utilizzare le sue funzionalità",
7 | "Welcome to {0} version {1}! The extension is now active": "Benvenuto alla versione {0} {1}! L'estensione è ora attiva",
8 | "New version of {0} is available. Check out the release notes for version {1}": "È disponibile una nuova versione di {0}. Consulta le note sulla versione {1}",
9 | "Release Notes": "Note sulla versione",
10 | "Dismiss": "Ignora",
11 | "No active editor!": "Nessun editor attivo!",
12 | "No selection!": "Nessuna sele",
13 | "Operation cancelled!": "Operazione annullata!",
14 | "Error while finding files: {0}": "Errore durante la ricerca dei file: {0}",
15 | "Invalid file type!": "Tipo di file non valido!",
16 | "Error parsing {0}: {1}": "Errore durante l'analisi di {0}: {1}",
17 | "Content copied to clipboard": "Contenuto copiato negli appunti",
18 | "Content copied as JSON to clipboard": "Contenuto copiato come JSON negli appunti",
19 | "File Name: {0}\nLanguage: {1}\nLines: {2}\nVersion: {3}": "Nome file: {0}\nLingua: {1}\nRighe: {2}\nVersione: {3}",
20 | "Report Issues": "Segnala problemi",
21 | "Rate Us": "Valutaci",
22 | "No workspace folder available to save the image!": "Nessuna cartella dello spazio di lavoro disponibile per salvare l'immagine!",
23 | "Select a workspace folder to save the image": "Seleziona una cartella dello spazio di lavoro per salvare l'immagine",
24 | "Image saved to: {0}": "Immagine salvata in: {0}",
25 | "Enter the name of the type or structure generated": "Inserisci il nome del tipo o della struttura generata",
26 | "Enter the name of the type or structure, e.g., User, Post, etc.": "Inserisci il nome del tipo o della struttura, ad esempio, Utente, Post, ecc.",
27 | "The name of the type or structure is required!": "Il nome del tipo o della struttura è obbligatorio!"
28 | }
29 |
--------------------------------------------------------------------------------
/l10n/bundle.l10n.pt-br.json:
--------------------------------------------------------------------------------
1 | {
2 | "No workspace folders are open. Please open a workspace folder to use this extension": "Nenhuma pasta de espaço de trabalho está aberta. Por favor, abra uma pasta de espaço de trabalho para usar esta extensão",
3 | "Select a workspace folder to use. This folder will be used to load workspace-specific configuration for the extension": "Selecione uma pasta de espaço de trabalho para usar. Esta pasta será usada para carregar a configuração específica do espaço de trabalho para a extensão",
4 | "{0} is now enabled and ready to use": "{0} está agora ativado e pronto para usar",
5 | "{0} is now disabled": "{0} está agora desativado",
6 | "{0} is disabled in settings. Enable it to use its features": "{0} está desativado nas configurações. Ative-o para usar suas funcionalidades",
7 | "Welcome to {0} version {1}! The extension is now active": "Bem-vindo à versão {0} {1}! A extensão está agora ativa",
8 | "New version of {0} is available. Check out the release notes for version {1}": "Nova versão de {0} está disponível. Confira as notas de lançamento para a versão {1}",
9 | "Release Notes": "Notas de lançamento",
10 | "Dismiss": "Dispensar",
11 | "No active editor!": "Nenhum editor ativo!",
12 | "No selection!": "Nenhuma seleção!",
13 | "Operation cancelled!": "Operação cancelada!",
14 | "Error while finding files: {0}": "Erro ao encontrar arquivos: {0}",
15 | "Invalid file type!": "Tipo de arquivo inválido!",
16 | "Error parsing {0}: {1}": "Erro ao analisar {0}: {1}",
17 | "Content copied to clipboard": "Conteúdo copiado para a área de transferência",
18 | "Content copied as JSON to clipboard": "Conteúdo copiado como JSON para a área de transferência",
19 | "File Name: {0}\nLanguage: {1}\nLines: {2}\nVersion: {3}": "Nome do arquivo: {0}\nIdioma: {1}\nLinhas: {2}\nVersão: {3}",
20 | "Report Issues": "Relatar problemas",
21 | "Rate Us": "Avalie-nos",
22 | "No workspace folder available to save the image!": "Nenhuma pasta de espaço de trabalho disponível para salvar a imagem!",
23 | "Select a workspace folder to save the image": "Selecione uma pasta de espaço de trabalho para salvar a imagem",
24 | "Image saved to: {0}": "Imagem salva em: {0}",
25 | "Enter the name of the type or structure generated": "Digite o nome do tipo ou estrutura gerada",
26 | "Enter the name of the type or structure, e.g., User, Post, etc.": "Digite o nome do tipo ou estrutura, por exemplo, Usuário, Postagem, etc.",
27 | "The name of the type or structure is required!": "O nome do tipo ou estrutura é obrigatório!"
28 | }
29 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vscode-json-flow",
3 | "displayName": "JSON Flow",
4 | "description": "Transform JSON into interactive graphs in VSCode - Free & Open Source",
5 | "version": "1.13.0",
6 | "icon": "icon.png",
7 | "license": "MIT",
8 | "publisher": "imgildev",
9 | "author": {
10 | "name": "Manuel Gil",
11 | "email": "support@imgil.dev",
12 | "url": "https://imgil.dev/"
13 | },
14 | "sponsor": {
15 | "url": "https://github.com/sponsors/manuelgil"
16 | },
17 | "engines": {
18 | "vscode": "^1.88.0"
19 | },
20 | "categories": [
21 | "Other"
22 | ],
23 | "keywords": [
24 | "cfg",
25 | "csv",
26 | "data",
27 | "dotenv",
28 | "env",
29 | "explorer",
30 | "fileview",
31 | "flow view",
32 | "flow",
33 | "flowview",
34 | "graph view",
35 | "graph",
36 | "graphview",
37 | "hcl",
38 | "ini",
39 | "json flow",
40 | "json schema",
41 | "json view",
42 | "json-flow",
43 | "json-schema",
44 | "json-xml",
45 | "json",
46 | "json5",
47 | "jsonc",
48 | "jsonflow",
49 | "jsonschema",
50 | "jsonview",
51 | "live preview",
52 | "manager",
53 | "node",
54 | "nodes",
55 | "preview",
56 | "properties",
57 | "schema",
58 | "toml",
59 | "tree",
60 | "treeview",
61 | "tsv",
62 | "view",
63 | "visualizer",
64 | "vscode-extension",
65 | "vscode-json-flow",
66 | "vscode",
67 | "xml",
68 | "yaml",
69 | "yml"
70 | ],
71 | "homepage": "https://github.com/ManuelGil/vscode-json-flow",
72 | "repository": {
73 | "type": "git",
74 | "url": "https://github.com/ManuelGil/vscode-json-flow"
75 | },
76 | "bugs": {
77 | "url": "https://github.com/ManuelGil/vscode-json-flow/issues"
78 | },
79 | "activationEvents": [],
80 | "main": "./out/extension.js",
81 | "l10n": "./l10n",
82 | "contributes": {
83 | "configuration": {
84 | "title": "JSON Flow",
85 | "properties": {
86 | "jsonFlow.enable": {
87 | "type": "boolean",
88 | "default": true,
89 | "scope": "resource",
90 | "description": "%jsonFlow.enable%"
91 | },
92 | "jsonFlow.files.include": {
93 | "type": "array",
94 | "default": [
95 | "json",
96 | "jsonc",
97 | "json5",
98 | "cfg",
99 | "csv",
100 | "env",
101 | "hcl",
102 | "ini",
103 | "properties",
104 | "toml",
105 | "tsv",
106 | "xml",
107 | "yaml",
108 | "yml"
109 | ],
110 | "scope": "resource",
111 | "description": "%jsonFlow.files.include%"
112 | },
113 | "jsonFlow.files.exclude": {
114 | "type": "array",
115 | "default": [
116 | "**/node_modules/**",
117 | "**/dist/**",
118 | "**/out/**",
119 | "**/build/**",
120 | "**/vendor/**"
121 | ],
122 | "scope": "resource",
123 | "description": "%jsonFlow.files.exclude%"
124 | },
125 | "jsonFlow.files.showPath": {
126 | "type": "boolean",
127 | "default": true,
128 | "scope": "resource",
129 | "description": "%jsonFlow.files.showPath%"
130 | },
131 | "jsonFlow.graph.showValues": {
132 | "type": "boolean",
133 | "default": true,
134 | "scope": "resource",
135 | "description": "%jsonFlow.graph.showValues%"
136 | },
137 | "jsonFlow.graph.nodeWidth": {
138 | "type": "number",
139 | "default": 200,
140 | "scope": "resource",
141 | "description": "%jsonFlow.graph.nodeWidth%"
142 | },
143 | "jsonFlow.graph.nodeHeight": {
144 | "type": "number",
145 | "default": 50,
146 | "scope": "resource",
147 | "description": "%jsonFlow.graph.nodeHeight%"
148 | },
149 | "jsonFlow.graph.nodeBorderColor": {
150 | "type": "string",
151 | "default": "white",
152 | "scope": "resource",
153 | "description": "%jsonFlow.graph.nodeBorderColor%"
154 | },
155 | "jsonFlow.graph.nodeColor": {
156 | "type": "string",
157 | "default": "white",
158 | "scope": "resource",
159 | "description": "%jsonFlow.graph.nodeColor%"
160 | },
161 | "jsonFlow.graph.edgeColor": {
162 | "type": "string",
163 | "default": "white",
164 | "scope": "resource",
165 | "description": "%jsonFlow.graph.edgeColor%"
166 | },
167 | "jsonFlow.graph.layoutDirection": {
168 | "type": "string",
169 | "default": "TB",
170 | "enum": [
171 | "TB",
172 | "LR"
173 | ],
174 | "scope": "resource",
175 | "description": "%jsonFlow.graph.layoutDirection%"
176 | },
177 | "jsonFlow.image.folder": {
178 | "type": "string",
179 | "default": "json-flow/images",
180 | "scope": "resource",
181 | "description": "%jsonFlow.image.folder%"
182 | }
183 | }
184 | },
185 | "commands": [
186 | {
187 | "command": "jsonFlow.files.refreshList",
188 | "title": "%jsonFlow.files.refreshList%",
189 | "category": "JSON Flow",
190 | "icon": "$(refresh)"
191 | },
192 | {
193 | "command": "jsonFlow.files.openFile",
194 | "title": "%jsonFlow.files.openFile%",
195 | "category": "JSON Flow"
196 | },
197 | {
198 | "command": "jsonFlow.files.copyContent",
199 | "title": "%jsonFlow.files.copyContent%",
200 | "category": "JSON Flow"
201 | },
202 | {
203 | "command": "jsonFlow.files.copyContentAsJson",
204 | "title": "%jsonFlow.files.copyContentAsJson%",
205 | "category": "JSON Flow"
206 | },
207 | {
208 | "command": "jsonFlow.files.copyContentPartialAsJson",
209 | "title": "%jsonFlow.files.copyContentPartialAsJson%",
210 | "category": "JSON Flow"
211 | },
212 | {
213 | "command": "jsonFlow.files.getFileProperties",
214 | "title": "%jsonFlow.files.getFileProperties%",
215 | "category": "JSON Flow"
216 | },
217 | {
218 | "command": "jsonFlow.json.showPartialPreview",
219 | "title": "%jsonFlow.json.showPartialPreview%",
220 | "category": "JSON Flow"
221 | },
222 | {
223 | "command": "jsonFlow.json.showPreview",
224 | "title": "%jsonFlow.json.showPreview%",
225 | "category": "JSON Flow"
226 | },
227 | {
228 | "command": "jsonFlow.files.convertToJson",
229 | "title": "%jsonFlow.files.convertToJson%",
230 | "category": "JSON Flow"
231 | },
232 | {
233 | "command": "jsonFlow.files.convertPartialToJson",
234 | "title": "%jsonFlow.files.convertPartialToJson%",
235 | "category": "JSON Flow"
236 | },
237 | {
238 | "command": "jsonFlow.files.convertToType",
239 | "title": "%jsonFlow.files.convertToType%",
240 | "category": "JSON Flow"
241 | },
242 | {
243 | "command": "jsonFlow.files.convertPartialToType",
244 | "title": "%jsonFlow.files.convertPartialToType%",
245 | "category": "JSON Flow"
246 | }
247 | ],
248 | "submenus": [
249 | {
250 | "id": "jsonFlow.explorer.submenu",
251 | "label": "JSON Flow"
252 | },
253 | {
254 | "id": "jsonFlow.editor.submenu",
255 | "label": "JSON Flow"
256 | }
257 | ],
258 | "menus": {
259 | "view/title": [
260 | {
261 | "command": "jsonFlow.files.refreshList",
262 | "when": "view == jsonFlow.filesView",
263 | "group": "navigation"
264 | }
265 | ],
266 | "view/item/context": [
267 | {
268 | "command": "jsonFlow.files.openFile",
269 | "when": "view == jsonFlow.filesView && viewItem =~ /.(json|jsonc|json5|cfg|csv|env|hcl|ini|properties|toml|tsv|xml|yaml|yml)/",
270 | "group": "1_navigation"
271 | },
272 | {
273 | "command": "jsonFlow.files.convertToJson",
274 | "when": "view == jsonFlow.filesView && viewItem =~ /.(cfg|csv|env|hcl|ini|properties|toml|tsv|xml|yaml|yml)/",
275 | "group": "2_modification"
276 | },
277 | {
278 | "command": "jsonFlow.files.convertToType",
279 | "when": "view == jsonFlow.filesView && viewItem =~ /.(json|jsonc|json5|cfg|csv|env|hcl|ini|properties|toml|tsv|xml|yaml|yml)/",
280 | "group": "2_modification"
281 | },
282 | {
283 | "command": "jsonFlow.files.copyContent",
284 | "when": "view == jsonFlow.filesView && viewItem =~ /.(json|jsonc|json5|cfg|csv|env|hcl|ini|properties|toml|tsv|xml|yaml|yml)/",
285 | "group": "3_cutcopypaste@1"
286 | },
287 | {
288 | "command": "jsonFlow.files.copyContentAsJson",
289 | "when": "view == jsonFlow.filesView && viewItem =~ /.(cfg|csv|env|hcl|ini|properties|toml|tsv|xml|yaml|yml)/",
290 | "group": "3_cutcopypaste@2"
291 | },
292 | {
293 | "command": "jsonFlow.files.getFileProperties",
294 | "when": "view == jsonFlow.filesView && viewItem =~ /.(json|jsonc|json5|cfg|csv|env|hcl|ini|properties|toml|tsv|xml|yaml|yml)/",
295 | "group": "4_properties"
296 | }
297 | ],
298 | "explorer/context": [
299 | {
300 | "submenu": "jsonFlow.explorer.submenu",
301 | "group": "2_workspace",
302 | "when": "resourceExtname =~ /json|jsonc|json5|cfg|csv|env|hcl|ini|properties|toml|tsv|xml|yaml|yml/"
303 | }
304 | ],
305 | "editor/context": [
306 | {
307 | "submenu": "jsonFlow.editor.submenu",
308 | "group": "1_modification",
309 | "when": "editorHasSelection"
310 | }
311 | ],
312 | "jsonFlow.explorer.submenu": [
313 | {
314 | "command": "jsonFlow.json.showPreview",
315 | "title": "%jsonFlow.json.showPreview%",
316 | "group": "1_navigation"
317 | },
318 | {
319 | "command": "jsonFlow.files.convertToJson",
320 | "title": "%jsonFlow.files.convertToJson%",
321 | "when": "resourceExtname =~ /cfg|csv|env|hcl|ini|properties|toml|tsv|xml|yaml|yml/",
322 | "group": "2_modification"
323 | },
324 | {
325 | "command": "jsonFlow.files.convertToType",
326 | "title": "%jsonFlow.files.convertToType%",
327 | "when": "resourceExtname =~ /json|jsonc|json5|cfg|csv|env|hcl|ini|properties|toml|tsv|xml|yaml|yml/",
328 | "group": "2_modification"
329 | },
330 | {
331 | "command": "jsonFlow.files.copyContent",
332 | "title": "%jsonFlow.files.copyContent%",
333 | "when": "resourceExtname =~ /json|jsonc|json5|cfg|csv|env|hcl|ini|properties|toml|tsv|xml|yaml|yml/",
334 | "group": "3_cutcopypaste"
335 | },
336 | {
337 | "command": "jsonFlow.files.copyContentAsJson",
338 | "title": "%jsonFlow.files.copyContentAsJson%",
339 | "when": "resourceExtname =~ /cfg|csv|env|hcl|ini|properties|toml|tsv|xml|yaml|yml/",
340 | "group": "3_cutcopypaste"
341 | }
342 | ],
343 | "jsonFlow.editor.submenu": [
344 | {
345 | "command": "jsonFlow.json.showPartialPreview",
346 | "title": "%jsonFlow.json.showPartialPreview%",
347 | "group": "1_view"
348 | },
349 | {
350 | "command": "jsonFlow.files.convertPartialToJson",
351 | "title": "%jsonFlow.files.convertPartialToJson%",
352 | "when": "resourceExtname =~ /cfg|csv|env|hcl|ini|properties|toml|tsv|xml|yaml|yml/",
353 | "group": "2_modification"
354 | },
355 | {
356 | "command": "jsonFlow.files.convertPartialToType",
357 | "title": "%jsonFlow.files.convertPartialToType%",
358 | "when": "resourceExtname =~ /json|jsonc|json5|cfg|csv|env|hcl|ini|properties|toml|tsv|xml|yaml|yml/",
359 | "group": "2_modification"
360 | },
361 | {
362 | "command": "jsonFlow.files.copyContentPartialAsJson",
363 | "title": "%jsonFlow.files.copyContentPartialAsJson%",
364 | "when": "resourceExtname =~ /cfg|csv|env|hcl|ini|properties|toml|tsv|xml|yaml|yml/",
365 | "group": "3_cutcopypaste"
366 | }
367 | ]
368 | },
369 | "viewsWelcome": [
370 | {
371 | "view": "jsonFlow.filesView",
372 | "contents": "%viewsWelcome.jsonFlow.filesView%"
373 | }
374 | ],
375 | "viewsContainers": {
376 | "activitybar": [
377 | {
378 | "id": "json-explorer",
379 | "title": "JSON Flow",
380 | "icon": "./assets/logo.svg"
381 | }
382 | ]
383 | },
384 | "views": {
385 | "json-explorer": [
386 | {
387 | "id": "jsonFlow.filesView",
388 | "name": "%jsonFlow.filesView%",
389 | "visibility": "visible"
390 | },
391 | {
392 | "id": "jsonFlow.feedbackView",
393 | "name": "%jsonFlow.feedbackView%",
394 | "visibility": "visible"
395 | }
396 | ]
397 | },
398 | "jsonValidation": [
399 | {
400 | "fileMatch": ".vscode/settings.json",
401 | "url": "./schemas/config.schema.json"
402 | }
403 | ]
404 | },
405 | "scripts": {
406 | "vscode:prepublish": "npm run build && npm run compile",
407 | "compile": "rimraf out && tsc -p ./ && cpy dist/* out/webview",
408 | "watch": "tsc -watch -p ./",
409 | "pretest": "npm run compile && npm run lint",
410 | "dev": "vite",
411 | "build": "tsc --p ./tsconfig.web.json && vite build",
412 | "preview": "vite preview",
413 | "format": "biome format --write",
414 | "lint": "biome lint --write",
415 | "lint:check": "biome check --write",
416 | "test": "vscode-test",
417 | "compodoc": "npx compodoc -p tsconfig.doc.json -d compodoc --theme readthedocs -s",
418 | "prepare": "husky",
419 | "release": "release-it"
420 | },
421 | "dependencies": {
422 | "@vscode/webview-ui-toolkit": "^1.4.0",
423 | "@xyflow/react": "^12.3.4",
424 | "dotenv": "^16.4.5",
425 | "entitree-flex": "^0.4.1",
426 | "fast-glob": "^3.3.2",
427 | "fast-xml-parser": "^4.5.0",
428 | "hcl-parser": "^0.1.1",
429 | "html-to-image": "^1.11.11",
430 | "ini": "^5.0.0",
431 | "json5": "^2.2.3",
432 | "quicktype-core": "^23.0.170",
433 | "react": "^18.3.1",
434 | "react-dom": "^18.3.1",
435 | "toml": "^3.0.0",
436 | "yaml": "^2.6.0"
437 | },
438 | "devDependencies": {
439 | "@biomejs/biome": "1.9.4",
440 | "@commitlint/cli": "^19.5.0",
441 | "@commitlint/config-conventional": "^19.5.0",
442 | "@compodoc/compodoc": "^1.1.26",
443 | "@release-it/keep-a-changelog": "^6.0.0",
444 | "@types/mocha": "^10.0.10",
445 | "@types/node": "^22.10.5",
446 | "@types/react": "^18.3.12",
447 | "@types/react-dom": "^18.3.1",
448 | "@types/vscode": "^1.88.0",
449 | "@typescript-eslint/eslint-plugin": "^8.17.0",
450 | "@typescript-eslint/parser": "^8.17.0",
451 | "@vitejs/plugin-react": "^4.3.3",
452 | "@vscode/l10n-dev": "^0.0.35",
453 | "@vscode/test-cli": "^0.0.10",
454 | "@vscode/test-electron": "^2.4.1",
455 | "autoprefixer": "^10.4.20",
456 | "cpy-cli": "^5.0.0",
457 | "eslint": "^9.16.0",
458 | "husky": "^9.1.6",
459 | "lint-staged": "^15.2.10",
460 | "postcss": "^8.4.47",
461 | "release-it": "^18.1.1",
462 | "rimraf": "^6.0.1",
463 | "tailwindcss": "^3.4.14",
464 | "typescript": "^5.7.2",
465 | "vite": "^5.4.10",
466 | "vscode-test": "^1.6.1"
467 | }
468 | }
469 |
--------------------------------------------------------------------------------
/package.nls.de.json:
--------------------------------------------------------------------------------
1 | {
2 | "jsonFlow.enable": "JSON Flow aktivieren",
3 | "jsonFlow.files.include": "Glob-Muster, die im Paket enthalten sein sollen. Der Standardwert ist json und jsonc",
4 | "jsonFlow.files.exclude": "Glob-Muster, die aus dem Paket ausgeschlossen werden sollen. Der Standardwert ist node_modules, dist, out, build und alle versteckten Dateien",
5 | "jsonFlow.files.showPath": "Den Dateipfad im Namen der Liste der generierten Dateien anzeigen",
6 | "jsonFlow.graph.showValues": "Die Werte der Knoten im Diagramm anzeigen",
7 | "jsonFlow.graph.nodeWidth": "Breite der Knoten im Diagramm. Der Standardwert ist 200",
8 | "jsonFlow.graph.nodeHeight": "Höhe der Knoten im Diagramm. Der Standardwert ist 50",
9 | "jsonFlow.graph.nodeBorderColor": "Farbe des Knotenrahmens im Diagramm. Der Standardwert ist 'white'",
10 | "jsonFlow.graph.nodeColor": "Farbe des Knotenfülls im Diagramm. Der Standardwert ist 'white'",
11 | "jsonFlow.graph.edgeColor": "Farbe der Kanten im Diagramm. Der Standardwert ist 'white'",
12 | "jsonFlow.graph.layoutDirection": "Layoutrichtung des Diagramms. TB für von oben nach unten und LR für von links nach rechts",
13 | "jsonFlow.image.folder": "Ordner, in dem die Diagramme gespeichert werden. Der Standardwert ist json-flow/images",
14 | "jsonFlow.files.refreshList": "Liste aktualisieren",
15 | "jsonFlow.files.openFile": "Datei öffnen",
16 | "jsonFlow.files.convertToJson": "In JSON konvertieren",
17 | "jsonFlow.files.convertPartialToJson": "Auswahl in JSON konvertieren",
18 | "jsonFlow.files.convertToType": "In Typ oder Struktur umwandeln",
19 | "jsonFlow.files.convertPartialToType": "Auswahl in Typ oder Struktur umwandeln",
20 | "jsonFlow.files.copyContent": "Inhalt in Zwischenablage kopieren",
21 | "jsonFlow.files.copyContentAsJson": "Inhalt als JSON kopieren",
22 | "jsonFlow.files.copyContentPartialAsJson": "Auswahl als JSON kopieren",
23 | "jsonFlow.files.getFileProperties": "Dateieigenschaften abrufen",
24 | "jsonFlow.json.showPreview": "JSON-Vorschau anzeigen",
25 | "jsonFlow.json.showPartialPreview": "Auswahl als JSON anzeigen",
26 | "jsonFlow.filesView": "Dateiliste",
27 | "jsonFlow.feedbackView": "Hilfe und Feedback",
28 | "viewsWelcome.jsonFlow.filesView": "Um Dateien effektiv zu erfassen, stellen Sie sicher, dass Sie den Dateityp in den Einstellungen des Arbeitsbereichs einschließen.\n[Arbeitsbereichseinstellung öffnen](command:workbench.action.openWorkspaceSettingsFile)\nWeitere Informationen zur Verwendung von JSON Flow [finden Sie in unserer Dokumentation](https://github.com/ManuelGil/vscode-json-flow)."
29 | }
30 |
--------------------------------------------------------------------------------
/package.nls.es.json:
--------------------------------------------------------------------------------
1 | {
2 | "jsonFlow.enable": "Activar JSON Flow",
3 | "jsonFlow.files.include": "Patrones Glob para incluir en el paquete. El valor predeterminado es json y jsonc",
4 | "jsonFlow.files.exclude": "Patrones Glob para excluir del paquete. El valor predeterminado es node_modules, dist, out, build y cualquier archivo oculto",
5 | "jsonFlow.files.showPath": "Mostrar la ruta del archivo en el nombre de la lista de archivos generados",
6 | "jsonFlow.graph.showValues": "Mostrar los valores de los nodos en el gráfico",
7 | "jsonFlow.graph.nodeWidth": "Ancho de los nodos en el gráfico. El valor predeterminado es 200",
8 | "jsonFlow.graph.nodeHeight": "Altura de los nodos en el gráfico. El valor predeterminado es 50",
9 | "jsonFlow.graph.nodeBorderColor": "Color del borde de los nodos en el gráfico. El valor predeterminado es 'white'",
10 | "jsonFlow.graph.nodeColor": "Color de relleno de los nodos en el gráfico. El valor predeterminado es 'white'",
11 | "jsonFlow.graph.edgeColor": "Color de los bordes en el gráfico. El valor predeterminado es 'white'",
12 | "jsonFlow.graph.layoutDirection": "Dirección de diseño del gráfico. TB para arriba hacía abajo y LR para izquierda a derecha",
13 | "jsonFlow.image.folder": "Carpeta donde se guardarán los gráficos. El valor predeterminado es json-flow/images",
14 | "jsonFlow.files.refreshList": "Refrescar Lista",
15 | "jsonFlow.files.openFile": "Abrir Archivo",
16 | "jsonFlow.files.convertToJson": "Convertir a JSON",
17 | "jsonFlow.files.convertPartialToJson": "Convertir Selección a JSON",
18 | "jsonFlow.files.convertToType": "Convertir a Tipo o Estructura",
19 | "jsonFlow.files.convertPartialToType": "Convertir Selección a Tipo o Estructura",
20 | "jsonFlow.files.copyContent": "Copiar Contenido al Portapapeles",
21 | "jsonFlow.files.copyContentAsJson": "Copiar Contenido como JSON",
22 | "jsonFlow.files.copyContentPartialAsJson": "Copiar Selección como JSON",
23 | "jsonFlow.files.getFileProperties": "Obtener Propiedades del Archivo",
24 | "jsonFlow.json.showPreview": "Mostrar Vista Previa de JSON",
25 | "jsonFlow.json.showPartialPreview": "Mostrar Selección como JSON",
26 | "jsonFlow.filesView": "Lista de Archivos",
27 | "jsonFlow.feedbackView": "Ayuda y Comentarios",
28 | "viewsWelcome.jsonFlow.filesView": "Para capturar archivos de forma efectiva, asegúrese de incluir el tipo de archivo dentro de la configuración del espacio de trabajo.\n[Abrir Configuración del Espacio de Trabajo](command:workbench.action.openWorkspaceSettingsFile)\nPara obtener más información sobre cómo usar JSON Flow [lea nuestra documentación](https://github.com/ManuelGil/vscode-json-flow)."
29 | }
30 |
--------------------------------------------------------------------------------
/package.nls.fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "jsonFlow.enable": "Activer JSON Flow",
3 | "jsonFlow.files.include": "Modèles globaux à inclure dans le paquet. La valeur par défaut est json et jsonc",
4 | "jsonFlow.files.exclude": "Modèles globaux à exclure du paquet. La valeur par défaut est node_modules, dist, out, build et tout fichier caché",
5 | "jsonFlow.files.showPath": "Afficher le chemin du fichier dans le nom de la liste des fichiers générés",
6 | "jsonFlow.graph.showValues": "Afficher les valeurs des nœuds dans le graphique",
7 | "jsonFlow.graph.nodeWidth": "Largeur des nœuds dans le graphique. La valeur par défaut est 200",
8 | "jsonFlow.graph.nodeHeight": "Hauteur des nœuds dans le graphique. La valeur par défaut est 50",
9 | "jsonFlow.graph.nodeBorderColor": "Couleur de la bordure des nœuds dans le graphique. La valeur par défaut est 'white'",
10 | "jsonFlow.graph.nodeColor": "Couleur de remplissage des nœuds dans le graphique. La valeur par défaut est 'white'",
11 | "jsonFlow.graph.edgeColor": "Couleur des bords dans le graphique. La valeur par défaut est 'white'",
12 | "jsonFlow.graph.layoutDirection": "Direction de la disposition du graphique. TB pour de haut en bas et LR pour de gauche à droite",
13 | "jsonFlow.image.folder": "Dossier où les graphiques seront enregistrés. La valeur par défaut est json-flow/images",
14 | "jsonFlow.files.refreshList": "Actualiser la liste",
15 | "jsonFlow.files.openFile": "Ouvrir le fichier",
16 | "jsonFlow.files.convertToJson": "Convertir en JSON",
17 | "jsonFlow.files.convertPartialToJson": "Convertir la sélection en JSON",
18 | "jsonFlow.files.convertToType": "Convertir en type ou structure",
19 | "jsonFlow.files.convertPartialToType": "Convertir la sélection en type ou structure",
20 | "jsonFlow.files.copyContent": "Copier le contenu dans le presse-papiers",
21 | "jsonFlow.files.copyContentAsJson": "Copier le contenu en tant que JSON",
22 | "jsonFlow.files.copyContentPartialAsJson": "Copier la sélection en tant que JSON",
23 | "jsonFlow.files.getFileProperties": "Obtenir les propriétés du fichier",
24 | "jsonFlow.json.showPreview": "Afficher l'aperçu JSON",
25 | "jsonFlow.json.showPartialPreview": "Afficher la sélection en tant que JSON",
26 | "jsonFlow.filesView": "Liste des fichiers",
27 | "jsonFlow.feedbackView": "Aide et retour",
28 | "viewsWelcome.jsonFlow.filesView": "Pour capturer efficacement des fichiers, assurez-vous d'inclure le type de fichier dans les paramètres de l'espace de travail.\n[Ouvrir les paramètres de l'espace de travail](command:workbench.action.openWorkspaceSettingsFile)\nPour en savoir plus sur l'utilisation de JSON Flow [lisez notre documentation](https://github.com/ManuelGil/vscode-json-flow)."
29 | }
30 |
--------------------------------------------------------------------------------
/package.nls.it.json:
--------------------------------------------------------------------------------
1 | {
2 | "jsonFlow.enable": "Abilita JSON Flow",
3 | "jsonFlow.files.include": "Modelli di glob da includere nel pacchetto. L'impostazione predefinita è json e jsonc",
4 | "jsonFlow.files.exclude": "Modelli di glob da escludere dal pacchetto. L'impostazione predefinita è node_modules, dist, out, build e qualsiasi file nascosto",
5 | "jsonFlow.files.showPath": "Mostra il percorso del file nel nome dell'elenco dei file generati",
6 | "jsonFlow.graph.showValues": "Mostra i valori dei nodi nel grafico",
7 | "jsonFlow.graph.nodeWidth": "Larghezza dei nodi nel grafico. Il valore predefinito è 200",
8 | "jsonFlow.graph.nodeHeight": "Altezza dei nodi nel grafico. Il valore predefinito è 50",
9 | "jsonFlow.graph.nodeBorderColor": "Colore del bordo dei nodi nel grafico. Il valore predefinito è 'white'",
10 | "jsonFlow.graph.nodeColor": "Colore di riempimento dei nodi nel grafico. Il valore predefinito è 'white'",
11 | "jsonFlow.graph.edgeColor": "Colore dei bordi nel grafico. Il valore predefinito è 'white'",
12 | "jsonFlow.graph.layoutDirection": "Direzione del layout del grafico. TB per dall'alto in basso e LR per da sinistra a destra",
13 | "jsonFlow.image.folder": "Cartella in cui verranno salvati i grafici. L'impostazione predefinita è json-flow/images",
14 | "jsonFlow.files.refreshList": "Aggiorna Elenco",
15 | "jsonFlow.files.openFile": "Apri File",
16 | "jsonFlow.files.convertToJson": "Converti in JSON",
17 | "jsonFlow.files.convertPartialToJson": "Converti Selezione in JSON",
18 | "jsonFlow.files.convertToType": "Converti in Tipo o Struttura",
19 | "jsonFlow.files.convertPartialToType": "Converti Selezione in Tipo o Struttura",
20 | "jsonFlow.files.copyContent": "Copia Contenuto negli Appunti",
21 | "jsonFlow.files.copyContentAsJson": "Copia Contenuto come JSON",
22 | "jsonFlow.files.copyContentPartialAsJson": "Copia Selezione come JSON",
23 | "jsonFlow.files.getFileProperties": "Ottieni Proprietà del File",
24 | "jsonFlow.json.showPreview": "Mostra Anteprima JSON",
25 | "jsonFlow.json.showPartialPreview": "Mostra Selezione come JSON",
26 | "jsonFlow.filesView": "Elenco dei File",
27 | "jsonFlow.feedbackView": "Aiuto e Feedback",
28 | "viewsWelcome.jsonFlow.filesView": "Per catturare efficacemente i file, assicurati di includere il tipo di file nelle impostazioni dello spazio di lavoro.\n[Apri Impostazioni dello Spazio di Lavoro](command:workbench.action.openWorkspaceSettingsFile)\nPer saperne di più su come utilizzare JSON Flow [leggi la nostra documentazione](https://github.com/ManuelGil/vscode-json-flow)."
29 | }
30 |
--------------------------------------------------------------------------------
/package.nls.json:
--------------------------------------------------------------------------------
1 | {
2 | "jsonFlow.enable": "Enable JSON Flow",
3 | "jsonFlow.files.include": "Glob patterns to include in the package. The default is json and jsonc",
4 | "jsonFlow.files.exclude": "Glob patterns to exclude from the package. The default is node_modules, dist, out, build, and any hidden files",
5 | "jsonFlow.files.showPath": "Show the path of the file in the name of the list of generated files",
6 | "jsonFlow.graph.showValues": "Show the values of the nodes in the graph",
7 | "jsonFlow.graph.nodeWidth": "Width of the nodes in the graph. The default is 200",
8 | "jsonFlow.graph.nodeHeight": "Height of the nodes in the graph. The default is 50",
9 | "jsonFlow.graph.nodeBorderColor": "Color of the border of the nodes in the graph. The default is 'white'",
10 | "jsonFlow.graph.nodeColor": "Color of the fill of the nodes in the graph. The default is 'white'",
11 | "jsonFlow.graph.edgeColor": "Color of the edges in the graph. The default is 'white'",
12 | "jsonFlow.graph.layoutDirection": "Graph layout direction. TB for top to bottom and LR for left to right",
13 | "jsonFlow.image.folder": "Folder where the graphs will be saved. The default is json-flow/images",
14 | "jsonFlow.files.refreshList": "Refresh List",
15 | "jsonFlow.files.openFile": "Open File",
16 | "jsonFlow.files.convertToJson": "Convert to JSON",
17 | "jsonFlow.files.convertPartialToJson": "Convert Selection to JSON",
18 | "jsonFlow.files.convertToType": "Convert to Type or Structure",
19 | "jsonFlow.files.convertPartialToType": "Convert Selection to Type or Structure",
20 | "jsonFlow.files.copyContent": "Copy Content to Clipboard",
21 | "jsonFlow.files.copyContentAsJson": "Copy Content as JSON",
22 | "jsonFlow.files.copyContentPartialAsJson": "Copy Selection as JSON",
23 | "jsonFlow.files.getFileProperties": "Get File Properties",
24 | "jsonFlow.json.showPreview": "Show JSON Preview",
25 | "jsonFlow.json.showPartialPreview": "Show Selection as JSON",
26 | "jsonFlow.filesView": "List of Files",
27 | "jsonFlow.feedbackView": "Help and Feedback",
28 | "viewsWelcome.jsonFlow.filesView": "To effectively capture files, ensure you include the file type within the workspace settings.\n[Open Workspace Setting](command:workbench.action.openWorkspaceSettingsFile)\nTo learn more about how to use the JSON Flow [read our docs](https://github.com/ManuelGil/vscode-json-flow)."
29 | }
30 |
--------------------------------------------------------------------------------
/package.nls.pt-br.json:
--------------------------------------------------------------------------------
1 | {
2 | "jsonFlow.enable": "Ativar JSON Flow",
3 | "jsonFlow.files.include": "Padrões Glob para incluir no pacote. O padrão é json e jsonc",
4 | "jsonFlow.files.exclude": "Padrões Glob para excluir do pacote. O padrão é node_modules, dist, out, build e quaisquer arquivos ocultos",
5 | "jsonFlow.files.showPath": "Mostrar o caminho do arquivo no nome da lista de arquivos gerados",
6 | "jsonFlow.graph.showValues": "Mostrar os valores dos nós no gráfico",
7 | "jsonFlow.graph.nodeWidth": "Largura dos nós no gráfico. O padrão é 200",
8 | "jsonFlow.graph.nodeHeight": "Altura dos nós no gráfico. O padrão é 50",
9 | "jsonFlow.graph.nodeBorderColor": "Cor da borda dos nós no gráfico. O padrão é 'white'",
10 | "jsonFlow.graph.nodeColor": "Cor do preenchimento dos nós no gráfico. O padrão é 'white'",
11 | "jsonFlow.graph.edgeColor": "Cor das bordas no gráfico. O padrão é 'white'",
12 | "jsonFlow.graph.layoutDirection": "Direção do layout do gráfico. TB para de cima para baixo e LR para da esquerda para a direita",
13 | "jsonFlow.image.folder": "Pasta onde os gráficos serão salvos. O padrão é json-flow/images",
14 | "jsonFlow.files.refreshList": "Atualizar Lista",
15 | "jsonFlow.files.openFile": "Abrir Arquivo",
16 | "jsonFlow.files.convertToJson": "Converter para JSON",
17 | "jsonFlow.files.convertPartialToJson": "Converter Seleção para JSON",
18 | "jsonFlow.files.convertToType": "Converter para Tipo ou Estrutura",
19 | "jsonFlow.files.convertPartialToType": "Converter Seleção para Tipo ou Estrutura",
20 | "jsonFlow.files.copyContent": "Copiar Conteúdo para a Área de Transferência",
21 | "jsonFlow.files.copyContentAsJson": "Copiar Conteúdo como JSON",
22 | "jsonFlow.files.copyContentPartialAsJson": "Copiar Seleção como JSON",
23 | "jsonFlow.files.getFileProperties": "Obter Propriedades do Arquivo",
24 | "jsonFlow.json.showPreview": "Mostrar Visualização JSON",
25 | "jsonFlow.json.showPartialPreview": "Mostrar Seleção como JSON",
26 | "jsonFlow.filesView": "Lista de Arquivos",
27 | "jsonFlow.feedbackView": "Ajuda e Feedback",
28 | "viewsWelcome.jsonFlow.filesView": "Para capturar efetivamente arquivos, certifique-se de incluir o tipo de arquivo nas configurações do espaço de trabalho.\n[Abrir Configurações do Espaço de Trabalho](command:workbench.action.openWorkspaceSettingsFile)\nPara saber mais sobre como usar o JSON Flow [leia nossa documentação](https://github.com/ManuelGil/vscode-json-flow)."
29 | }
30 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | };
7 |
--------------------------------------------------------------------------------
/schemas/config.schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json-schema.org/draft-07/schema#",
3 | "type": "object",
4 | "properties": {
5 | "jsonFlow.enable": {
6 | "type": "string",
7 | "default": "Enable JSON Flow",
8 | "description": "Enable JSON Flow"
9 | },
10 | "jsonFlow.files.include": {
11 | "type": "array",
12 | "default": [
13 | "json",
14 | "jsonc",
15 | "json5",
16 | "cfg",
17 | "csv",
18 | "env",
19 | "hcl",
20 | "ini",
21 | "properties",
22 | "toml",
23 | "tsv",
24 | "xml",
25 | "yaml",
26 | "yml"
27 | ],
28 | "scope": "resource",
29 | "description": "Glob patterns to include in the package."
30 | },
31 | "jsonFlow.files.exclude": {
32 | "type": "array",
33 | "default": [
34 | "**/node_modules/**",
35 | "**/dist/**",
36 | "**/out/**",
37 | "**/build/**",
38 | "**/vendor/**"
39 | ],
40 | "scope": "resource",
41 | "description": "Glob patterns to exclude from the package. The default is node_modules, dist, out, build, and any hidden files."
42 | },
43 | "jsonFlow.files.showPath": {
44 | "type": "boolean",
45 | "default": true,
46 | "scope": "resource",
47 | "description": "Show the path of the file in the name of the list of generated files"
48 | },
49 | "jsonFlow.graph.showValues": {
50 | "type": "boolean",
51 | "default": true,
52 | "scope": "resource",
53 | "description": "Show the values of the nodes in the graph"
54 | },
55 | "jsonFlow.graph.nodeWidth": {
56 | "type": "number",
57 | "default": 200,
58 | "scope": "resource",
59 | "description": "Width of the nodes in the graph"
60 | },
61 | "jsonFlow.graph.nodeHeight": {
62 | "type": "number",
63 | "default": 50,
64 | "scope": "resource",
65 | "description": "Height of the nodes in the graph"
66 | },
67 | "jsonFlow.graph.nodeBorderColor": {
68 | "type": "string",
69 | "default": "white",
70 | "scope": "resource",
71 | "description": "Color of the border of the nodes in the graph"
72 | },
73 | "jsonFlow.graph.nodeColor": {
74 | "type": "string",
75 | "default": "white",
76 | "scope": "resource",
77 | "description": "Color of the fill of the nodes in the graph"
78 | },
79 | "jsonFlow.graph.edgeColor": {
80 | "type": "string",
81 | "default": "white",
82 | "scope": "resource",
83 | "description": "Color of the edges in the graph"
84 | },
85 | "jsonFlow.graph.layoutDirection": {
86 | "type": "string",
87 | "default": "TB",
88 | "enum": ["TB", "LR"],
89 | "scope": "resource",
90 | "description": "The direction of the layout of the graph. TB is top to bottom, LR is left to right."
91 | },
92 | "jsonFlow.image.folder": {
93 | "type": "string",
94 | "default": "json-flow/images",
95 | "scope": "resource",
96 | "description": "The folder where the graphs will be saved."
97 | }
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/app/configs/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelGil/vscode-json-flow/d6515cd6b0259e893793e999deafcef49df6082f/src/app/configs/.gitkeep
--------------------------------------------------------------------------------
/src/app/configs/constants.config.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * EXTENSION_ID: The unique identifier of the extension.
3 | * @type {string}
4 | * @public
5 | * @memberof Constants
6 | * @example
7 | * console.log(EXTENSION_ID);
8 | *
9 | * @returns {string} - The unique identifier of the extension
10 | */
11 | export const EXTENSION_ID: string = 'jsonFlow';
12 |
13 | /**
14 | * EXTENSION_NAME: The name of the extension.
15 | * @type {string}
16 | * @public
17 | * @memberof Constants
18 | * @example
19 | * console.log(EXTENSION_NAME);
20 | *
21 | * @returns {string} - The name of the extension
22 | */
23 | export const EXTENSION_NAME: string = 'JSON Flow';
24 |
25 | /**
26 | * USER_PUBLISHER: The publisher of the extension.
27 | * @type {string}
28 | * @public
29 | * @memberof Constants
30 | * @example
31 | * console.log(USER_PUBLISHER);
32 | *
33 | * @returns {string} - The publisher of the extension
34 | */
35 | export const USER_PUBLISHER: string = 'imgildev';
36 |
37 | /**
38 | * EXTENSION_REPOSITORY_URL: The repository URL of the extension.
39 | * @type {string}
40 | * @public
41 | * @memberof Constants
42 | * @example
43 | * console.log(EXTENSION_REPOSITORY_URL);
44 | *
45 | * @returns {string} - The repository URL of the extension
46 | */
47 | export const EXTENSION_REPOSITORY_URL: string =
48 | 'https://github.com/ManuelGil/vscode-json-flow';
49 |
50 | /**
51 | * EXTENSION_MARKETPLACE_URL: The marketplace URL of the extension.
52 | * @type {string}
53 | * @public
54 | * @memberof Constants
55 | * @example
56 | * console.log(EXTENSION_MARKETPLACE_URL);
57 | *
58 | * @returns {string} - The marketplace URL of the extension
59 | */
60 | export const EXTENSION_MARKETPLACE_URL: string =
61 | 'https://marketplace.visualstudio.com/items?itemName=imgildev.vscode-json-flow';
62 |
63 | /**
64 | * EXTENSION_BUGS_URL: The bugs URL of the extension.
65 | * @type {string}
66 | * @public
67 | * @memberof Constants
68 | * @example
69 | * console.log(EXTENSION_BUGS_URL);
70 | *
71 | * @returns {string} - The bugs URL of the extension
72 | */
73 | export const EXTENSION_BUGS_URL: string =
74 | 'https://github.com/ManuelGil/vscode-json-flow/issues';
75 |
76 | /**
77 | * INCLUDE: The files to include.
78 | * @type {string[]}
79 | * @public
80 | * @memberof Constants
81 | * @example
82 | * console.log(INCLUDE);
83 | *
84 | * @returns {string[]} - The files to include
85 | */
86 | export const INCLUDE: string[] = [
87 | 'json',
88 | 'jsonc',
89 | 'json5',
90 | 'cfg',
91 | 'csv',
92 | 'env',
93 | 'hcl',
94 | 'ini',
95 | 'properties',
96 | 'toml',
97 | 'tsv',
98 | 'xml',
99 | 'yaml',
100 | 'yml',
101 | ];
102 |
103 | /**
104 | * EXCLUDE: The files to exclude.
105 | * @type {string[]}
106 | * @public
107 | * @memberof Constants
108 | * @example
109 | * console.log(EXCLUDE);
110 | *
111 | * @returns {string[]} - The files to exclude
112 | */
113 | export const EXCLUDE: string[] = [
114 | '**/node_modules/**',
115 | '**/dist/**',
116 | '**/out/**',
117 | '**/build/**',
118 | '**/vendor/**',
119 | ];
120 |
121 | /**
122 | * SHOW_PATH: Whether to show the path or not.
123 | * @type {boolean}
124 | * @public
125 | * @memberof Constants
126 | * @example
127 | * console.log(SHOW_PATH);
128 | *
129 | * @returns {boolean} - Whether to show the path or not
130 | */
131 | export const SHOW_PATH: boolean = true;
132 |
133 | /**
134 | * SHOW_VALUES: Whether to show the values or not.
135 | * @type {boolean}
136 | * @public
137 | * @memberof Constants
138 | * @example
139 | * console.log(SHOW_VALUES);
140 | *
141 | * @returns {boolean} - Whether to show the values or not
142 | */
143 | export const SHOW_VALUES: boolean = true;
144 |
145 | /**
146 | * NODE_WIDTH: The node width.
147 | * @type {number}
148 | * @public
149 | * @memberof Constants
150 | * @example
151 | * console.log(NODE_WIDTH);
152 | *
153 | * @returns {number} - The node width
154 | */
155 | export const NODE_WIDTH: number = 200;
156 |
157 | /**
158 | * NODE_HEIGHT: The node height.
159 | * @type {number}
160 | * @public
161 | * @memberof Constants
162 | * @example
163 | * console.log(NODE_HEIGHT);
164 | *
165 | * @returns {number} - The node height
166 | */
167 | export const NODE_HEIGHT: number = 50;
168 |
169 | /**
170 | * NODE_BORDER_COLOR: The node border color.
171 | * @type {string}
172 | * @public
173 | * @memberof Constants
174 | * @example
175 | * console.log(NODE_BORDER_COLOR);
176 | *
177 | * @returns {string} - The node border color
178 | */
179 | export const NODE_BORDER_COLOR = 'white';
180 |
181 | /**
182 | * NODE_COLOR: The node color.
183 | * @type {string}
184 | * @public
185 | * @memberof Constants
186 | * @example
187 | * console.log(NODE_COLOR);
188 | *
189 | * @returns {string} - The node color
190 | */
191 | export const NODE_COLOR = 'white';
192 |
193 | /**
194 | * EDGE_COLOR: The edge color.
195 | * @type {string}
196 | * @public
197 | * @memberof Constants
198 | * @example
199 | * console.log(EDGE_COLOR);
200 | *
201 | * @returns {string} - The edge color
202 | */
203 | export const EDGE_COLOR = 'white';
204 |
205 | /**
206 | * LAYOUT_DIRECTION: The layout direction.
207 | * @type {string}
208 | * @public
209 | * @memberof Constants
210 | * @example
211 | * console.log(LAYOUT_DIRECTION);
212 | *
213 | * @returns {string} - The layout direction
214 | */
215 | export const LAYOUT_DIRECTION: 'TB' | 'LR' = 'TB';
216 |
217 | /**
218 | * IMAGE_FOLDER: The image folder.
219 | * @type {string}
220 | * @public
221 | * @memberof Constants
222 | * @example
223 | * console.log(IMAGE_FOLDER);
224 | *
225 | * @returns {string} - The image folder
226 | */
227 | export const IMAGE_FOLDER: string = 'json-flow/images';
228 |
--------------------------------------------------------------------------------
/src/app/configs/extension.config.ts:
--------------------------------------------------------------------------------
1 | import { WorkspaceConfiguration } from 'vscode';
2 |
3 | import {
4 | EDGE_COLOR,
5 | EXCLUDE,
6 | IMAGE_FOLDER,
7 | INCLUDE,
8 | LAYOUT_DIRECTION,
9 | NODE_BORDER_COLOR,
10 | NODE_COLOR,
11 | NODE_HEIGHT,
12 | NODE_WIDTH,
13 | SHOW_PATH,
14 | SHOW_VALUES,
15 | } from './constants.config';
16 |
17 | /**
18 | * The Config class.
19 | *
20 | * @class
21 | * @classdesc The class that represents the configuration of the extension.
22 | * @export
23 | * @public
24 | * @property {WorkspaceConfiguration} config - The workspace configuration
25 | * @property {boolean} enable - Whether the extension is enabled or not
26 | * @property {string[]} include - The files to include
27 | * @property {string[]} exclude - The files to exclude
28 | * @property {boolean} showPath - Whether to show the path or not
29 | * @property {boolean} showValues - Whether to show the values or not
30 | * @property {number} nodeWidth - The node width
31 | * @property {number} nodeHeight - The node height
32 | * @property {string} nodeBorderColor - The node border color
33 | * @property {string} nodeColor - The node color
34 | * @property {string} edgeColor - The edge color
35 | * @property {'TB' | 'LR'} layoutDirection - The layout direction
36 | * @property {string} imageFolder - The image folder
37 | * @example
38 | * const config = new Config(workspace.getConfiguration());
39 | * console.log(config.include);
40 | * console.log(config.exclude);
41 | */
42 | export class ExtensionConfig {
43 | // -----------------------------------------------------------------
44 | // Properties
45 | // -----------------------------------------------------------------
46 |
47 | // Public properties
48 | /**
49 | * Whether the extension is enabled or not.
50 | * @type {boolean}
51 | * @public
52 | * @memberof ExtensionConfig
53 | * @example
54 | * const config = new ExtensionConfig(workspace.getConfiguration());
55 | * console.log(config.enable);
56 | */
57 | enable: boolean;
58 |
59 | /**
60 | * The files to include.
61 | * @type {string[]}
62 | * @public
63 | * @memberof Config
64 | * @example
65 | * const config = new Config(workspace.getConfiguration());
66 | * console.log(config.include);
67 | */
68 | include: string[];
69 | /**
70 | * The files to exclude.
71 | * @type {string[]}
72 | * @public
73 | * @memberof Config
74 | * @example
75 | * const config = new Config(workspace.getConfiguration());
76 | * console.log(config.exclude);
77 | */
78 | exclude: string[];
79 | /**
80 | * Whether to show the path or not.
81 | * @type {boolean}
82 | * @public
83 | * @memberof Config
84 | * @example
85 | * const config = new Config(workspace.getConfiguration());
86 | * console.log(config.showPath);
87 | */
88 | showPath: boolean;
89 | /**
90 | * Whether to show the values or not.
91 | * @type {boolean}
92 | * @public
93 | * @memberof Config
94 | * @example
95 | * const config = new Config(workspace.getConfiguration());
96 | * console.log(config.showValues);
97 | */
98 | showValues: boolean;
99 | /**
100 | * The node width.
101 | * @type {number}
102 | * @public
103 | * @memberof Config
104 | * @example
105 | * const config = new Config(workspace.getConfiguration());
106 | * console.log(config.nodeWidth);
107 | */
108 | nodeWidth: number;
109 | /**
110 | * The node height.
111 | * @type {number}
112 | * @public
113 | * @memberof Config
114 | * @example
115 | * const config = new Config(workspace.getConfiguration());
116 | * console.log(config.nodeHeight);
117 | */
118 | nodeHeight: number;
119 | /**
120 | * The node border color.
121 | * @type {string}
122 | * @public
123 | * @memberof Config
124 | * @example
125 | * const config = new Config(workspace.getConfiguration());
126 | * console.log(config.nodeBorderColor);
127 | */
128 | nodeBorderColor: string;
129 | /**
130 | * The node color.
131 | * @type {string}
132 | * @public
133 | * @memberof Config
134 | * @example
135 | * const config = new Config(workspace.getConfiguration());
136 | * console.log(config.nodeColor);
137 | */
138 | nodeColor: string;
139 | /**
140 | * The edge color.
141 | * @type {string}
142 | * @public
143 | * @memberof Config
144 | * @example
145 | * const config = new Config(workspace.getConfiguration());
146 | * console.log(config.edgeColor);
147 | */
148 | edgeColor: string;
149 | /**
150 | * The layout direction.
151 | * @type {'TB' | 'LR'}
152 | * @public
153 | * @memberof Config
154 | * @example
155 | * const config = new Config(workspace.getConfiguration());
156 | * console.log(config.layoutDirection);
157 | */
158 | layoutDirection: 'TB' | 'LR';
159 | /**
160 | * The image folder.
161 | * @type {string}
162 | * @public
163 | * @memberof Config
164 | * @example
165 | * const config = new Config(workspace.getConfiguration());
166 | * console.log(config.imageFolder);
167 | */
168 | imageFolder: string;
169 |
170 | // -----------------------------------------------------------------
171 | // Constructor
172 | // -----------------------------------------------------------------
173 |
174 | /**
175 | * Constructor for the Config class.
176 | *
177 | * @constructor
178 | * @param {WorkspaceConfiguration} config - The workspace configuration
179 | * @public
180 | * @memberof Config
181 | */
182 | constructor(readonly config: WorkspaceConfiguration) {
183 | this.enable = config.get('enable', true);
184 | this.include = config.get('files.include', INCLUDE);
185 | this.exclude = config.get('files.exclude', EXCLUDE);
186 | this.showPath = config.get('files.showPath', SHOW_PATH);
187 | this.showValues = config.get('graph.showValues', SHOW_VALUES);
188 | this.nodeWidth = config.get('graph.nodeWidth', NODE_WIDTH);
189 | this.nodeHeight = config.get('graph.nodeHeight', NODE_HEIGHT);
190 | this.nodeBorderColor = config.get(
191 | 'graph.nodeBorderColor',
192 | NODE_BORDER_COLOR,
193 | );
194 | this.nodeColor = config.get('graph.nodeColor', NODE_COLOR);
195 | this.edgeColor = config.get('graph.edgeColor', EDGE_COLOR);
196 | this.layoutDirection = config.get<'TB' | 'LR'>(
197 | 'graph.layoutDirection',
198 | LAYOUT_DIRECTION,
199 | );
200 | this.imageFolder = config.get('image.folder', IMAGE_FOLDER);
201 | }
202 |
203 | // -----------------------------------------------------------------
204 | // Methods
205 | // -----------------------------------------------------------------
206 |
207 | // Public methods
208 | /**
209 | * The update method.
210 | *
211 | * @function update
212 | * @param {WorkspaceConfiguration} config - The workspace configuration
213 | * @public
214 | * @memberof Config
215 | * @example
216 | * const config = new Config(workspace.getConfiguration());
217 | * config.update(workspace.getConfiguration());
218 | */
219 | update(config: WorkspaceConfiguration): void {
220 | this.enable = config.get('enable', this.enable);
221 | this.include = config.get('files.include', this.include);
222 | this.exclude = config.get('files.exclude', this.exclude);
223 | this.showPath = config.get('files.showPath', this.showPath);
224 | this.showValues = config.get('graph.showValues', this.showValues);
225 | this.nodeWidth = config.get('graph.nodeWidth', this.nodeWidth);
226 | this.nodeHeight = config.get('graph.nodeHeight', this.nodeHeight);
227 | this.nodeBorderColor = config.get(
228 | 'graph.nodeBorderColor',
229 | this.nodeBorderColor,
230 | );
231 | this.nodeColor = config.get('graph.nodeColor', this.nodeColor);
232 | this.edgeColor = config.get('graph.edgeColor', this.edgeColor);
233 | this.layoutDirection = config.get<'TB' | 'LR'>(
234 | 'graph.layoutDirection',
235 | this.layoutDirection,
236 | );
237 | this.imageFolder = config.get('image.folder', this.imageFolder);
238 | }
239 | }
240 |
--------------------------------------------------------------------------------
/src/app/configs/index.ts:
--------------------------------------------------------------------------------
1 | export * from './constants.config';
2 | export * from './extension.config';
3 |
--------------------------------------------------------------------------------
/src/app/controllers/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelGil/vscode-json-flow/d6515cd6b0259e893793e999deafcef49df6082f/src/app/controllers/.gitkeep
--------------------------------------------------------------------------------
/src/app/controllers/feedback.controller.ts:
--------------------------------------------------------------------------------
1 | import { Uri, env } from 'vscode';
2 |
3 | import { EXTENSION_BUGS_URL, EXTENSION_MARKETPLACE_URL } from '../configs';
4 |
5 | /**
6 | * The FeedbackController class.
7 | *
8 | * @class
9 | * @classdesc The class that represents the feedback controller.
10 | * @export
11 | * @public
12 | * @example
13 | * const controller = new FeedbackController();
14 | */
15 | export class FeedbackController {
16 | // -----------------------------------------------------------------
17 | // Methods
18 | // -----------------------------------------------------------------
19 |
20 | // Public methods
21 | /**
22 | * The reportIssues method.
23 | *
24 | * @function reportIssues
25 | * @public
26 | * @memberof FeedbackController
27 | *
28 | * @returns {void} - No return value
29 | */
30 | reportIssues(): void {
31 | env.openExternal(Uri.parse(EXTENSION_BUGS_URL));
32 | }
33 |
34 | /**
35 | * The rateUs method.
36 | *
37 | * @function rateUs
38 | * @public
39 | * @memberof FeedbackController
40 | *
41 | * @returns {void} - No return value
42 | */
43 | rateUs(): void {
44 | env.openExternal(
45 | Uri.parse(`${EXTENSION_MARKETPLACE_URL}&ssr=false#review-details`),
46 | );
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/app/controllers/files.controller.ts:
--------------------------------------------------------------------------------
1 | import fg from 'fast-glob';
2 | import { Range, ThemeIcon, Uri, env, l10n, window, workspace } from 'vscode';
3 |
4 | import { EXTENSION_ID, ExtensionConfig } from '../configs';
5 | import { FileType, isFileTypeSupported, parseJSONContent } from '../helpers';
6 | import { NodeModel } from '../models';
7 |
8 | /**
9 | * The FilesController class.
10 | *
11 | * @class
12 | * @classdesc The class that represents the list files controller.
13 | * @export
14 | * @public
15 | * @property {ExtensionConfig} config - The configuration object
16 | * @example
17 | * const controller = new FilesController(config);
18 | */
19 | export class FilesController {
20 | // -----------------------------------------------------------------
21 | // Constructor
22 | // -----------------------------------------------------------------
23 |
24 | /**
25 | * Constructor for the FilesController class
26 | *
27 | * @constructor
28 | * @param {ExtensionConfig} config - The configuration object
29 | * @public
30 | * @memberof FilesController
31 | */
32 | constructor(readonly config: ExtensionConfig) {}
33 |
34 | // -----------------------------------------------------------------
35 | // Methods
36 | // -----------------------------------------------------------------
37 |
38 | // Public methods
39 | /**
40 | * The getFiles method.
41 | *
42 | * @function getFiles
43 | * @public
44 | * @async
45 | * @memberof FilesController
46 | * @example
47 | * controller.getFiles();
48 | *
49 | * @returns {Promise} - The list of files
50 | */
51 | async getFiles(): Promise {
52 | // Get the files in the folder
53 | let folders: string[] = [];
54 | let files: Uri[] = [];
55 |
56 | if (!workspace.workspaceFolders) {
57 | const message = l10n.t('Operation cancelled!');
58 | window.showErrorMessage(message);
59 | return;
60 | }
61 |
62 | folders = workspace.workspaceFolders.map((folder) => folder.uri.fsPath);
63 |
64 | const { include, exclude } = this.config;
65 |
66 | const includedFilePatterns = `**/*.{${include.join(',')}}`;
67 | const excludedFilePatterns = Array.isArray(exclude) ? exclude : [exclude];
68 |
69 | for (const folder of folders) {
70 | const result = await this.findFiles(
71 | folder,
72 | [includedFilePatterns],
73 | excludedFilePatterns,
74 | );
75 |
76 | files.push(...result);
77 | }
78 |
79 | if (files.length !== 0) {
80 | const nodes: NodeModel[] = [];
81 |
82 | files.sort((a, b) => a.path.localeCompare(b.path));
83 |
84 | for (const file of files) {
85 | const document = await workspace.openTextDocument(file);
86 |
87 | const path = workspace.asRelativePath(document.fileName);
88 | let filename = path.split('/').pop();
89 |
90 | if (filename && this.config.showPath) {
91 | const folder = path.split('/').slice(0, -1).join('/');
92 |
93 | filename += folder ? ` (${folder})` : ' (root)';
94 | }
95 |
96 | nodes.push(
97 | new NodeModel(
98 | filename ?? 'Untitled',
99 | new ThemeIcon('file'),
100 | {
101 | command: `${EXTENSION_ID}.json.showPreview`,
102 | title: 'Open Preview',
103 | arguments: [document.uri],
104 | },
105 | document.uri,
106 | document.fileName,
107 | ),
108 | );
109 | }
110 |
111 | return nodes;
112 | }
113 |
114 | return;
115 | }
116 |
117 | /**
118 | * The openFile method.
119 | *
120 | * @function openFile
121 | * @param {NodeModel} node - The node model
122 | * @public
123 | * @memberof FilesController
124 | * @example
125 | * controller.openFile('file:///path/to/file');
126 | *
127 | * @returns {Promise} - The promise
128 | */
129 | openFile(node: NodeModel) {
130 | if (node.resourceUri) {
131 | workspace.openTextDocument(node.resourceUri).then((filename) => {
132 | window.showTextDocument(filename);
133 | });
134 | }
135 | }
136 |
137 | /**
138 | * The copyContent method.
139 | *
140 | * @function copyContent
141 | * @param {NodeModel} node - The node model
142 | * @public
143 | * @memberof FilesController
144 | * @example
145 | * controller.copyContent('file:///path/to/file');
146 | *
147 | * @returns {void} - The promise
148 | */
149 | copyContent(node: NodeModel) {
150 | if (node.resourceUri) {
151 | workspace.openTextDocument(node.resourceUri).then((document) => {
152 | const message = l10n.t('Content copied to clipboard');
153 | env.clipboard.writeText(document.getText());
154 | window.showInformationMessage(message);
155 | });
156 | }
157 | }
158 |
159 | /**
160 | * The copyContentAsJson method.
161 | *
162 | * @function copyContentAsJson
163 | * @param {NodeModel | Uri} node - The node model
164 | * @public
165 | * @memberof FilesController
166 | * @example
167 | * controller.copyContentAsJson('file:///path/to/file');
168 | *
169 | * @returns {void} - The promise
170 | */
171 | copyContentAsJson(node: NodeModel) {
172 | if (node) {
173 | // Get the resource URI
174 | const resourceUri = node instanceof NodeModel ? node.resourceUri : node;
175 |
176 | // Check if the resource URI is valid
177 | if (!resourceUri) {
178 | const message = l10n.t('Operation cancelled!');
179 | window.showErrorMessage(message);
180 | return;
181 | }
182 |
183 | // Open the text document
184 | workspace.openTextDocument(resourceUri).then(async (document) => {
185 | // Get the language ID and file name
186 | const { languageId, fileName } = document;
187 |
188 | // Determine the file type, defaulting to 'json' if unsupported
189 | let fileType = languageId;
190 |
191 | if (!isFileTypeSupported(fileType)) {
192 | const fileExtension = fileName.split('.').pop();
193 |
194 | fileType = fileExtension;
195 | }
196 |
197 | // Parse JSON content
198 | const jsonContent = parseJSONContent(
199 | document.getText(),
200 | fileType as FileType,
201 | );
202 |
203 | // Check if the content is null
204 | if (jsonContent === null) {
205 | return;
206 | }
207 |
208 | // Copy the JSON content to the clipboard
209 | env.clipboard.writeText(JSON.stringify(jsonContent, null, 2));
210 |
211 | // Show the message
212 | const message = l10n.t('Content copied as JSON to clipboard');
213 | window.showInformationMessage(message);
214 | });
215 | }
216 | }
217 |
218 | /**
219 | * The copyContentPartialAsJson method.
220 | *
221 | * @function copyContentPartialAsJson
222 | * @public
223 | * @memberof FilesController
224 | * @example
225 | * controller.copyContentPartialAsJson();
226 | *
227 | * @returns {void} - The promise
228 | */
229 | copyContentPartialAsJson() {
230 | // Get the active text editor
231 | const editor = window.activeTextEditor;
232 |
233 | // Check if there is an active editor
234 | if (!editor) {
235 | const message = l10n.t('No active editor!');
236 | window.showErrorMessage(message);
237 | return;
238 | }
239 |
240 | // Check if there is a selection
241 | const selection = editor.selection;
242 |
243 | if (selection.isEmpty) {
244 | const message = l10n.t('No selection!');
245 | window.showErrorMessage(message);
246 | return;
247 | }
248 |
249 | // Get the selection range
250 | const selectionRange = new Range(
251 | selection.start.line,
252 | selection.start.character,
253 | selection.end.line,
254 | selection.end.character,
255 | );
256 |
257 | // Get the language ID and file name
258 | const { languageId, fileName } = editor.document;
259 |
260 | let fileType = languageId;
261 |
262 | let text = editor.document.getText(selectionRange);
263 |
264 | if (
265 | [
266 | 'javascript',
267 | 'javascriptreact',
268 | 'typescript',
269 | 'typescriptreact',
270 | ].includes(fileType)
271 | ) {
272 | fileType = 'json';
273 |
274 | text = text
275 | .replace(/'([^']+)'/g, '"$1"')
276 | .replace(/(['"])?([a-zA-Z0-9_]+)(['"])?:/g, '"$2":')
277 | .replace(/,*\s*\n*\]/g, ']')
278 | .replace(/{\s*\n*/g, '{')
279 | .replace(/,*\s*\n*};*/g, '}');
280 | }
281 |
282 | if (!isFileTypeSupported(fileType)) {
283 | const fileExtension = fileName.split('.').pop();
284 |
285 | fileType = isFileTypeSupported(fileExtension) ? fileExtension : 'jsonc';
286 | }
287 |
288 | // Parse JSON content
289 | const jsonContent = parseJSONContent(text, fileType as FileType);
290 |
291 | // Check if the JSON content is null
292 | if (jsonContent === null) {
293 | return;
294 | }
295 |
296 | // Copy the JSON content to the clipboard
297 | env.clipboard.writeText(JSON.stringify(jsonContent, null, 2));
298 |
299 | // Show the message
300 | const message = l10n.t('Content copied as JSON to clipboard');
301 | window.showInformationMessage(message);
302 | }
303 |
304 | /**
305 | * The getFileProperties method.
306 | *
307 | * @function getFileProperties
308 | * @param {NodeModel} node - The node model
309 | * @public
310 | * @memberof FilesController
311 | * @example
312 | * controller.getFileProperties('file:///path/to/file');
313 | *
314 | * @returns {void} - The promise
315 | */
316 | getFileProperties(node: NodeModel) {
317 | if (node.resourceUri) {
318 | workspace.openTextDocument(node.resourceUri).then(async (document) => {
319 | const { fileName, languageId, lineCount, version } = document;
320 |
321 | // Show the message
322 | const message = l10n.t(
323 | 'File Name: {0}\nLanguage: {1}\nLines: {2}\nVersion: {3}',
324 | [fileName, languageId, lineCount, version],
325 | );
326 |
327 | await window.showInformationMessage(message, { modal: true });
328 | });
329 | }
330 | }
331 |
332 | // Private methods
333 | /**
334 | * The findFiles method.
335 | *
336 | * @function findFiles
337 | * @param {string} baseDir - The base directory
338 | * @param {string[]} include - The include pattern
339 | * @param {string[]} exclude - The exclude pattern
340 | * @private
341 | * @async
342 | * @memberof FilesController
343 | * @example
344 | * controller.findFiles('baseDir', ['include'], ['exclude']);
345 | *
346 | * @returns {Promise} - The promise with the files
347 | */
348 | private async findFiles(
349 | baseDir: string,
350 | include: string[], // Include patterns
351 | exclude: string[], // Exclude patterns
352 | allowRecursion: boolean = true, // Toggle recursive search
353 | ): Promise {
354 | // Configure fast-glob options
355 | const options = {
356 | cwd: baseDir, // Set base directory for searching
357 | absolute: true, // Ensure paths are absolute
358 | onlyFiles: true, // Match only files, not directories
359 | dot: true, // Include files and directories starting with a dot
360 | deep: allowRecursion ? undefined : 1, // Toggle recursion
361 | ignore: exclude, // Exclude patterns
362 | };
363 |
364 | try {
365 | // Use fast-glob to find matching files
366 | const filePaths = await fg(include, options);
367 |
368 | // Convert file paths to VS Code Uri objects
369 | return filePaths.sort().map((filePath) => Uri.file(filePath));
370 | } catch (error) {
371 | const message = l10n.t('Error while finding files: {0}', [error]);
372 | window.showErrorMessage(message);
373 | return [];
374 | }
375 | }
376 | }
377 |
--------------------------------------------------------------------------------
/src/app/controllers/index.ts:
--------------------------------------------------------------------------------
1 | export * from './feedback.controller';
2 | export * from './files.controller';
3 | export * from './json.controller';
4 | export * from './transform.controller';
5 |
--------------------------------------------------------------------------------
/src/app/controllers/json.controller.ts:
--------------------------------------------------------------------------------
1 | import { existsSync, mkdirSync, writeFileSync } from 'fs';
2 | import { dirname, join } from 'path';
3 | import { ExtensionContext, Range, Uri, l10n, window, workspace } from 'vscode';
4 | import { ExtensionConfig } from '../configs';
5 | import {
6 | FileType,
7 | generateTree,
8 | isFileTypeSupported,
9 | parseJSONContent,
10 | } from '../helpers';
11 | import { JSONProvider } from '../providers';
12 |
13 | /**
14 | * The JsonController class.
15 | *
16 | * @class
17 | * @classdesc The class that represents the JSON controller.
18 | * @export
19 | * @public
20 | * @property {ExtensionContext} context - The extension context
21 | * @example
22 | * const controller = new JsonController(context);
23 | */
24 | export class JsonController {
25 | // -----------------------------------------------------------------
26 | // Properties
27 | // -----------------------------------------------------------------
28 |
29 | // Public properties
30 | /**
31 | * The webview configuration.
32 | *
33 | * @public
34 | * @memberof JsonController
35 | * @type {any}
36 | */
37 | static webviewConfiguration: { [key: string]: string | number };
38 |
39 | /**
40 | * The image folder.
41 | *
42 | * @public
43 | * @memberof JsonController
44 | * @type {string}
45 | */
46 | static imageFolder: string;
47 |
48 | // Private properties
49 | /**
50 | * The preview delay constant.
51 | * @type {number}
52 | * @private
53 | * @memberof JsonController
54 | * @example
55 | * private _processingDelay: number = 1000;
56 | */
57 | private _processingDelay: number = 1000; // Delay constant for preview initialization
58 |
59 | // -----------------------------------------------------------------
60 | // Constructor
61 | // -----------------------------------------------------------------
62 |
63 | /**
64 | * Constructor for the JsonController class
65 | *
66 | * @constructor
67 | * @param {ExtensionContext} context - The extension context
68 | * @public
69 | * @memberof JsonController
70 | */
71 | constructor(
72 | readonly context: ExtensionContext,
73 | readonly config: ExtensionConfig,
74 | ) {
75 | // Set the webview configuration
76 | JsonController.webviewConfiguration = {
77 | nodeWidth: config.nodeWidth,
78 | nodeHeight: config.nodeHeight,
79 | nodeBorderColor: config.nodeBorderColor,
80 | nodeColor: config.nodeColor,
81 | edgeColor: config.edgeColor,
82 | layoutDirection: config.layoutDirection,
83 | };
84 | // Set the image folder
85 | JsonController.imageFolder = config.imageFolder;
86 | }
87 |
88 | // -----------------------------------------------------------------
89 | // Methods
90 | // -----------------------------------------------------------------
91 |
92 | // Public methods
93 | /**
94 | * The showPreview method.
95 | *
96 | * @function showPreview
97 | * @param {Uri} uri - The URI of the file
98 | * @public
99 | * @memberof JsonController
100 | * @example
101 | * controller.showPreview(uri);
102 | *
103 | * @returns {void}
104 | */
105 | showPreview(uri: Uri): void {
106 | // Open the text document
107 | workspace.openTextDocument(uri.fsPath).then((document) => {
108 | // Get the language ID and file name
109 | const { languageId, fileName } = document;
110 |
111 | // Determine the file type, defaulting to 'json' if unsupported
112 | let fileType = languageId;
113 |
114 | if (!isFileTypeSupported(fileType)) {
115 | const fileExtension = fileName.split('.').pop();
116 |
117 | fileType = fileExtension;
118 | }
119 |
120 | // Parse JSON content
121 | const jsonContent = parseJSONContent(
122 | document.getText(),
123 | fileType as FileType,
124 | );
125 |
126 | // Check if the JSON content is null
127 | if (jsonContent === null) {
128 | return;
129 | }
130 |
131 | // Derive the file name for the preview panel title
132 | const displayName = fileName.split(/[\\/]/).pop() || 'JSON Flow';
133 |
134 | // Initialize the webview panel
135 | const panel = JSONProvider.createPanel(this.context.extensionUri);
136 |
137 | panel.title = displayName;
138 |
139 | const data = generateTree(jsonContent, this.config.showValues);
140 |
141 | const layoutDirection = this.config.layoutDirection;
142 |
143 | // Post the message to the webview with a delay
144 | setTimeout(() => {
145 | panel.webview.postMessage({
146 | type: 'setJson',
147 | layoutDirection,
148 | data,
149 | });
150 | }, this._processingDelay);
151 | });
152 | }
153 |
154 | /**
155 | * The showPartialPreview method.
156 | *
157 | * @function showPartialPreview
158 | * @public
159 | * @memberof JsonController
160 | * @example
161 | * controller.showPartialPreview();
162 | *
163 | * @returns {void}
164 | */
165 | showPartialPreview(): void {
166 | // Get the active text editor
167 | const editor = window.activeTextEditor;
168 |
169 | // Check if there is an active editor
170 | if (!editor) {
171 | const message = l10n.t('No active editor!');
172 | window.showErrorMessage(message);
173 | return;
174 | }
175 |
176 | // Check if there is a selection
177 | const selection = editor.selection;
178 |
179 | if (selection.isEmpty) {
180 | const message = l10n.t('No selection!');
181 | window.showErrorMessage(message);
182 | return;
183 | }
184 |
185 | // Get the selection range
186 | const selectionRange = new Range(
187 | selection.start.line,
188 | selection.start.character,
189 | selection.end.line,
190 | selection.end.character,
191 | );
192 |
193 | // Get the language ID and file name
194 | const { languageId, fileName } = editor.document;
195 |
196 | let fileType = languageId;
197 |
198 | let text = editor.document.getText(selectionRange);
199 |
200 | if (
201 | [
202 | 'javascript',
203 | 'javascriptreact',
204 | 'typescript',
205 | 'typescriptreact',
206 | ].includes(fileType)
207 | ) {
208 | fileType = 'json';
209 |
210 | text = text
211 | .replace(/'([^']+)'/g, '"$1"')
212 | .replace(/(['"])?([a-zA-Z0-9_]+)(['"])?:/g, '"$2":')
213 | .replace(/,*\s*\n*\]/g, ']')
214 | .replace(/{\s*\n*/g, '{')
215 | .replace(/,*\s*\n*};*/g, '}');
216 | }
217 |
218 | if (!isFileTypeSupported(fileType)) {
219 | const fileExtension = fileName.split('.').pop();
220 |
221 | fileType = isFileTypeSupported(fileExtension) ? fileExtension : 'jsonc';
222 | }
223 |
224 | // Parse JSON content
225 | const jsonContent = parseJSONContent(text, fileType as FileType);
226 |
227 | // Check if the JSON content is null
228 | if (jsonContent === null) {
229 | return;
230 | }
231 |
232 | // Derive the file name for the preview panel title
233 | const displayName = fileName.split(/[\\/]/).pop() || 'JSON Flow';
234 |
235 | // Initialize the webview panel
236 | const panel = JSONProvider.createPanel(this.context.extensionUri);
237 |
238 | panel.title = displayName;
239 |
240 | const data = generateTree(jsonContent, this.config.showValues);
241 |
242 | const layoutDirection = this.config.layoutDirection;
243 |
244 | // Post the message to the webview with a delay
245 | setTimeout(() => {
246 | panel.webview.postMessage({
247 | type: 'setJson',
248 | layoutDirection,
249 | data,
250 | });
251 | }, this._processingDelay);
252 | }
253 |
254 | /**
255 | * The saveImage method.
256 | *
257 | * @function saveImage
258 | * @param {string} dataUrl - The data URL
259 | * @public
260 | * @memberof JsonController
261 | * @example
262 | * controller.saveImage(dataUrl);
263 | *
264 | * @returns {Promise}
265 | */
266 | static async saveImage(data: string): Promise {
267 | const base64Data = data.replace(/^data:image\/png;base64,/, ''); // Remove metadata
268 | const buffer = Buffer.from(base64Data, 'base64'); // Convert base64 to binary
269 |
270 | // Generate a random filename with the date and time as a prefix and the .png extension
271 | // The filename won't be have a special characters or spaces to avoid issues
272 | const fileName = `json-flow-${new Date().toISOString().replace(/[^0-9]/g, '')}.png`;
273 |
274 | // Define the file path
275 | let filePath: string;
276 |
277 | // Get the workspace folders
278 | const workspaceFolders = workspace.workspaceFolders;
279 | if (!workspaceFolders || workspaceFolders.length === 0) {
280 | window.showErrorMessage(
281 | l10n.t('No workspace folder available to save the image!'),
282 | );
283 | return;
284 | }
285 |
286 | // Optionally, prompt the user to select a workspace folder if multiple are available
287 | if (workspaceFolders.length === 1) {
288 | filePath = join(
289 | workspaceFolders[0].uri.fsPath,
290 | this.imageFolder,
291 | fileName,
292 | );
293 | } else {
294 | // await window.showWorkspaceFolderPick({placeHolder});
295 | const folder = await window.showWorkspaceFolderPick({
296 | placeHolder: l10n.t('Select a workspace folder to save the image'),
297 | });
298 |
299 | if (!folder) {
300 | const message = l10n.t('Operation cancelled!');
301 | window.showErrorMessage(message);
302 | return;
303 | }
304 |
305 | // Save the file in the selected workspace folder
306 | filePath = join(folder.uri.fsPath, this.imageFolder, fileName);
307 | }
308 |
309 | // Create the directory if it doesn't exist
310 | if (!existsSync(dirname(filePath))) {
311 | await mkdirSync(dirname(filePath), { recursive: true });
312 | }
313 |
314 | // Write the file to the disk
315 | writeFileSync(filePath, buffer);
316 |
317 | // Show a message to the user
318 | window.showInformationMessage(l10n.t('Image saved to: {0}', filePath));
319 | }
320 | }
321 |
--------------------------------------------------------------------------------
/src/app/controllers/transform.controller.ts:
--------------------------------------------------------------------------------
1 | import {
2 | InputData,
3 | jsonInputForTargetLanguage,
4 | quicktype,
5 | } from 'quicktype-core';
6 | import { Range, Uri, l10n, window, workspace } from 'vscode';
7 | import { FileType, isFileTypeSupported, parseJSONContent } from '../helpers';
8 | import { NodeModel } from '../models';
9 |
10 | /**
11 | * The TransformController class.
12 | *
13 | * @class
14 | * @classdesc The class that represents the example controller.
15 | * @export
16 | * @public
17 | * @example
18 | * const controller = new TransformController();
19 | */
20 | export class TransformController {
21 | // -----------------------------------------------------------------
22 | // Methods
23 | // -----------------------------------------------------------------
24 |
25 | // Public methods
26 |
27 | /**
28 | * The convertToJson method.
29 | *
30 | * @function convertToJson
31 | * @param {NodeModel | Uri} node - The node model
32 | * @public
33 | * @memberof FilesController
34 | * @example
35 | * controller.convertToJson('file:///path/to/file');
36 | *
37 | * @returns {void} - The promise
38 | */
39 | convertToJson(node: NodeModel | Uri) {
40 | if (node) {
41 | // Get the resource URI
42 | const resourceUri = node instanceof NodeModel ? node.resourceUri : node;
43 |
44 | // Check if the resource URI is valid
45 | if (!resourceUri) {
46 | const message = l10n.t('Operation cancelled!');
47 | window.showErrorMessage(message);
48 | return;
49 | }
50 |
51 | // Open the text document
52 | workspace.openTextDocument(resourceUri).then(async (document) => {
53 | // Get the language ID and file name
54 | const { languageId, fileName } = document;
55 |
56 | // Determine the file type, defaulting to 'json' if unsupported
57 | let fileType = languageId;
58 |
59 | if (!isFileTypeSupported(fileType)) {
60 | const fileExtension = fileName.split('.').pop();
61 |
62 | fileType = fileExtension;
63 | }
64 |
65 | // Parse JSON content
66 | const jsonContent = parseJSONContent(
67 | document.getText(),
68 | fileType as FileType,
69 | );
70 |
71 | // Check if the content is null
72 | if (jsonContent === null) {
73 | return;
74 | }
75 |
76 | // Open the JSON document
77 | const jsonDocument = await workspace.openTextDocument({
78 | language: 'json',
79 | content: JSON.stringify(jsonContent, null, 2),
80 | });
81 |
82 | // Show the JSON document
83 | window.showTextDocument(jsonDocument);
84 | });
85 | }
86 | }
87 |
88 | /**
89 | * The convertPartialToJson method.
90 | *
91 | * @function convertPartialToJson
92 | * @public
93 | * @memberof FilesController
94 | * @example
95 | * controller.convertPartialToJson();
96 | *
97 | * @returns {void} - The promise
98 | */
99 | async convertPartialToJson() {
100 | // Get the active text editor
101 | const editor = window.activeTextEditor;
102 |
103 | // Check if there is an active editor
104 | if (!editor) {
105 | const message = l10n.t('No active editor!');
106 | window.showErrorMessage(message);
107 | return;
108 | }
109 |
110 | // Check if there is a selection
111 | const selection = editor.selection;
112 |
113 | if (selection.isEmpty) {
114 | const message = l10n.t('No selection!');
115 | window.showErrorMessage(message);
116 | return;
117 | }
118 |
119 | // Get the selection range
120 | const selectionRange = new Range(
121 | selection.start.line,
122 | selection.start.character,
123 | selection.end.line,
124 | selection.end.character,
125 | );
126 |
127 | // Get the language ID and file name
128 | const { languageId, fileName } = editor.document;
129 |
130 | let fileType = languageId;
131 |
132 | let text = editor.document.getText(selectionRange);
133 |
134 | if (
135 | [
136 | 'javascript',
137 | 'javascriptreact',
138 | 'typescript',
139 | 'typescriptreact',
140 | ].includes(fileType)
141 | ) {
142 | fileType = 'jsonc';
143 |
144 | text = text
145 | .replace(/'([^']+)'/g, '"$1"')
146 | .replace(/(['"])?([a-zA-Z0-9_]+)(['"])?:/g, '"$2":')
147 | .replace(/,*\s*\n*\]/g, ']')
148 | .replace(/{\s*\n*/g, '{')
149 | .replace(/,*\s*\n*};*/g, '}');
150 | }
151 |
152 | if (!isFileTypeSupported(fileType)) {
153 | const fileExtension = fileName.split('.').pop();
154 |
155 | fileType = isFileTypeSupported(fileExtension) ? fileExtension : 'jsonc';
156 | }
157 |
158 | // Parse JSON content
159 | const jsonContent = parseJSONContent(text, fileType as FileType);
160 |
161 | // Check if the JSON content is null
162 | if (jsonContent === null) {
163 | return;
164 | }
165 |
166 | // Open the JSON document
167 | const jsonDocument = await workspace.openTextDocument({
168 | language: 'json',
169 | content: JSON.stringify(jsonContent, null, 2),
170 | });
171 |
172 | // Show the JSON document
173 | window.showTextDocument(jsonDocument);
174 | }
175 |
176 | /**
177 | * The convertToType method.
178 | *
179 | * @function convertToType
180 | * @param {NodeModel | Uri} node - The node model
181 | * @param {string} targetLanguage - The target language
182 | * @public
183 | * @memberof FilesController
184 | * @example
185 | * controller.convertToType('file:///path/to/file', 'typescript');
186 | *
187 | * @returns {void} - The promise
188 | */
189 | async convertToType(node: NodeModel | Uri, targetLanguage: string) {
190 | if (node) {
191 | // Get the resource URI
192 | const resourceUri = node instanceof NodeModel ? node.resourceUri : node;
193 |
194 | // Check if the resource URI is valid
195 | if (!resourceUri) {
196 | const message = l10n.t('Operation cancelled!');
197 | window.showErrorMessage(message);
198 | return;
199 | }
200 |
201 | // Open the text document
202 | workspace.openTextDocument(resourceUri).then(async (document) => {
203 | // Get the language ID and file name
204 | const { languageId, fileName } = document;
205 |
206 | // Determine the file type, defaulting to 'json' if unsupported
207 | let fileType = languageId;
208 |
209 | if (!isFileTypeSupported(fileType)) {
210 | const fileExtension = fileName.split('.').pop();
211 |
212 | fileType = fileExtension;
213 | }
214 |
215 | // Parse JSON content
216 | const jsonContent = parseJSONContent(
217 | document.getText(),
218 | fileType as FileType,
219 | );
220 |
221 | // Check if the content is null
222 | if (jsonContent === null) {
223 | return;
224 | }
225 |
226 | // Get the name of the type or structure generated
227 | const typeName = await window.showInputBox({
228 | prompt: l10n.t('Enter the name of the type or structure generated'),
229 | placeHolder: l10n.t(
230 | 'Enter the name of the type or structure, e.g., User, Post, etc.',
231 | ),
232 | value: undefined,
233 | validateInput: (value) => {
234 | if (!value) {
235 | return l10n.t('The name of the type or structure is required!');
236 | }
237 |
238 | return;
239 | },
240 | });
241 |
242 | if (!typeName) {
243 | const message = l10n.t('Operation cancelled!');
244 | window.showErrorMessage(message);
245 | return;
246 | }
247 |
248 | // Create an instance of JSONInput
249 | const jsonInput = jsonInputForTargetLanguage(targetLanguage);
250 |
251 | // Add the JSON content to the JSONInput instance
252 | await jsonInput.addSource({
253 | name: typeName,
254 | samples: [JSON.stringify(jsonContent)],
255 | });
256 |
257 | // Create an instance of InputData
258 | const inputData = new InputData();
259 | inputData.addInput(jsonInput);
260 |
261 | // Generate the target language
262 | const { lines } = await quicktype({
263 | inputData,
264 | lang: targetLanguage,
265 | });
266 |
267 | // Open the JSON document
268 | const jsonDocument = await workspace.openTextDocument({
269 | language: this.mapLanguageId(targetLanguage),
270 | content: lines.join('\n'),
271 | });
272 |
273 | // Show the JSON document
274 | window.showTextDocument(jsonDocument);
275 | });
276 | }
277 | }
278 |
279 | /**
280 | * The convertPartialToType method.
281 | *
282 | * @function convertPartialToType
283 | * @param {string} targetLanguage - The target language
284 | * @public
285 | * @memberof FilesController
286 | * @example
287 | * controller.convertPartialToType('typescript');
288 | *
289 | * @returns {void} - The promise
290 | */
291 | async convertPartialToType(targetLanguage: string) {
292 | // Get the active text editor
293 | const editor = window.activeTextEditor;
294 |
295 | // Check if there is an active editor
296 | if (!editor) {
297 | const message = l10n.t('No active editor!');
298 | window.showErrorMessage(message);
299 | return;
300 | }
301 |
302 | // Check if there is a selection
303 | const selection = editor.selection;
304 |
305 | if (selection.isEmpty) {
306 | const message = l10n.t('No selection!');
307 | window.showErrorMessage(message);
308 | return;
309 | }
310 |
311 | // Get the selection range
312 | const selectionRange = new Range(
313 | selection.start.line,
314 | selection.start.character,
315 | selection.end.line,
316 | selection.end.character,
317 | );
318 |
319 | // Get the language ID and file name
320 | const { languageId, fileName } = editor.document;
321 |
322 | let fileType = languageId;
323 |
324 | let text = editor.document.getText(selectionRange);
325 |
326 | if (
327 | [
328 | 'javascript',
329 | 'javascriptreact',
330 | 'typescript',
331 | 'typescriptreact',
332 | ].includes(fileType)
333 | ) {
334 | fileType = 'jsonc';
335 |
336 | text = text
337 | .replace(/'([^']+)'/g, '"$1"')
338 | .replace(/(['"])?([a-zA-Z0-9_]+)(['"])?:/g, '"$2":')
339 | .replace(/,*\s*\n*\]/g, ']')
340 | .replace(/{\s*\n*/g, '{')
341 | .replace(/,*\s*\n*};*/g, '}');
342 | }
343 |
344 | if (!isFileTypeSupported(fileType)) {
345 | const fileExtension = fileName.split('.').pop();
346 |
347 | fileType = isFileTypeSupported(fileExtension) ? fileExtension : 'jsonc';
348 | }
349 |
350 | // Parse JSON content
351 | const jsonContent = parseJSONContent(text, fileType as FileType);
352 |
353 | // Check if the JSON content is null
354 | if (jsonContent === null) {
355 | return;
356 | }
357 |
358 | // Get the name of the type or structure generated
359 | const typeName = await window.showInputBox({
360 | prompt: l10n.t('Enter the name of the type or structure generated'),
361 | placeHolder: l10n.t(
362 | 'Enter the name of the type or structure, e.g., User, Post, etc.',
363 | ),
364 | value: undefined,
365 | validateInput: (value) => {
366 | if (!value) {
367 | return l10n.t('The name of the type or structure is required!');
368 | }
369 |
370 | return;
371 | },
372 | });
373 |
374 | if (!typeName) {
375 | const message = l10n.t('Operation cancelled!');
376 | window.showErrorMessage(message);
377 | return;
378 | }
379 |
380 | // Create an instance of JSONInput
381 | const jsonInput = jsonInputForTargetLanguage(targetLanguage);
382 |
383 | // Add the JSON content to the JSONInput instance
384 | await jsonInput.addSource({
385 | name: typeName,
386 | samples: [JSON.stringify(jsonContent)],
387 | });
388 |
389 | // Create an instance of InputData
390 | const inputData = new InputData();
391 | inputData.addInput(jsonInput);
392 |
393 | // Generate the target language
394 | const { lines } = await quicktype({
395 | inputData,
396 | lang: targetLanguage,
397 | });
398 |
399 | // Open the JSON document
400 | const jsonDocument = await workspace.openTextDocument({
401 | language: this.mapLanguageId(targetLanguage),
402 | content: lines.join('\n'),
403 | });
404 |
405 | // Show the JSON document
406 | window.showTextDocument(jsonDocument);
407 | }
408 |
409 | // Private methods
410 | /**
411 | * The mapLanguageId method.
412 | *
413 | * @function mapLanguageId
414 | * @param {string} targetLanguage - The target language
415 | * @private
416 | * @memberof TransformController
417 | * @example
418 | * const languageId = mapLanguageId('typescript');
419 | *
420 | * @returns {string} - The language ID
421 | */
422 | mapLanguageId(targetLanguage: string): string {
423 | switch (targetLanguage) {
424 | case 'ruby':
425 | return 'ruby';
426 | case 'javascript':
427 | return 'javascript';
428 | case 'flow':
429 | return 'javascript';
430 | case 'rust':
431 | return 'rust';
432 | case 'kotlin':
433 | return 'kotlin';
434 | case 'dart':
435 | return 'dart';
436 | case 'python':
437 | return 'python';
438 | case 'csharp':
439 | return 'csharp';
440 | case 'go':
441 | return 'go';
442 | case 'cpp':
443 | return 'cpp';
444 | case 'java':
445 | return 'java';
446 | case 'scala':
447 | return 'scala';
448 | case 'typescript':
449 | return 'typescript';
450 | case 'swift':
451 | return 'swift';
452 | case 'objective-c':
453 | return 'objective-c';
454 | case 'elm':
455 | return 'elm';
456 | case 'json-schema':
457 | return 'json';
458 | case 'pike':
459 | return 'pike';
460 | case 'prop-types':
461 | return 'javascript';
462 | case 'haskell':
463 | return 'haskell';
464 | case 'php':
465 | return 'php';
466 | default:
467 | return 'plaintext';
468 | }
469 | }
470 | }
471 |
--------------------------------------------------------------------------------
/src/app/helpers/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelGil/vscode-json-flow/d6515cd6b0259e893793e999deafcef49df6082f/src/app/helpers/.gitkeep
--------------------------------------------------------------------------------
/src/app/helpers/index.ts:
--------------------------------------------------------------------------------
1 | export * from './json.helper';
2 | export * from './security.helper';
3 | export * from './tree.helper';
4 |
--------------------------------------------------------------------------------
/src/app/helpers/json.helper.ts:
--------------------------------------------------------------------------------
1 | import * as dotenv from 'dotenv';
2 | import { XMLParser } from 'fast-xml-parser';
3 | import hcl from 'hcl-parser';
4 | import * as ini from 'ini';
5 | import json5 from 'json5';
6 | import * as toml from 'toml';
7 | import { l10n, window } from 'vscode';
8 | import * as yaml from 'yaml';
9 |
10 | /**
11 | * The FileType type.
12 | *
13 | * @type {FileType}
14 | */
15 | export type FileType =
16 | | 'csv'
17 | | 'dockercompose'
18 | | 'env'
19 | | 'hcl'
20 | | 'ini'
21 | | 'json'
22 | | 'json5'
23 | | 'jsonc'
24 | | 'properties'
25 | | 'toml'
26 | | 'tsv'
27 | | 'xml'
28 | | 'yaml'
29 | | 'yml';
30 |
31 | /**
32 | * Type guard to verify if a value is a valid FileType.
33 | *
34 | * @param value - The value to check.
35 | * @returns {value is FileType} - True if the value is a valid FileType, false otherwise.
36 | */
37 | export const isFileTypeSupported = (value: unknown): value is FileType => {
38 | const validFileTypes: FileType[] = [
39 | 'csv',
40 | 'dockercompose',
41 | 'env',
42 | 'hcl',
43 | 'ini',
44 | 'json',
45 | 'json5',
46 | 'jsonc',
47 | 'properties',
48 | 'toml',
49 | 'tsv',
50 | 'xml',
51 | 'yaml',
52 | 'yml',
53 | ];
54 |
55 | return validFileTypes.includes(value as FileType);
56 | };
57 |
58 | /**
59 | * The parseJSONContent function.
60 | *
61 | * @function parseJSONContent
62 | * @param {string} content - The content to parse
63 | * @param {FileType} type - The type of content
64 | * @returns {object | null} - The parsed content
65 | */
66 | export const parseJSONContent = (
67 | content: string,
68 | type: FileType,
69 | ): object | null => {
70 | try {
71 | switch (type) {
72 | case 'json':
73 | case 'jsonc':
74 | case 'json5':
75 | return json5.parse(content);
76 |
77 | case 'dockercompose':
78 | case 'yaml':
79 | case 'yml':
80 | return yaml.parse(content);
81 |
82 | case 'toml':
83 | return toml.parse(content);
84 |
85 | case 'ini':
86 | case 'properties':
87 | return ini.parse(content);
88 |
89 | case 'env':
90 | return dotenv.parse(content);
91 |
92 | case 'xml': {
93 | const parser = new XMLParser();
94 | return parser.parse(content);
95 | }
96 |
97 | case 'hcl':
98 | return hcl.parse(content);
99 |
100 | case 'csv': {
101 | const rows = content.trim().split('\n');
102 | const headers = rows[0].split(',').map((row) => row.replace('\r', ''));
103 | return rows.slice(1).map((row) => {
104 | const values = row.split(',');
105 | return headers.reduce((acc, header, index) => {
106 | acc[header] = values[index];
107 | return acc;
108 | }, {});
109 | });
110 | }
111 |
112 | case 'tsv': {
113 | const rows = content
114 | .trim()
115 | .split('\n')
116 | .map((row) => row.replace('\r', ''));
117 | const headers = rows[0].split('\t');
118 | return rows.slice(1).map((row) => {
119 | const values = row.split('\t');
120 | return headers.reduce((acc, header, index) => {
121 | acc[header] = values[index];
122 | return acc;
123 | }, {});
124 | });
125 | }
126 |
127 | default: {
128 | const message = l10n.t('Invalid file type!');
129 | window.showErrorMessage(message);
130 | return null;
131 | }
132 | }
133 | } catch (error) {
134 | const message = l10n.t('Error parsing {0}: {1}', [
135 | type.toUpperCase(),
136 | error.message,
137 | ]);
138 |
139 | window.showErrorMessage(message);
140 | return null;
141 | }
142 | };
143 |
--------------------------------------------------------------------------------
/src/app/helpers/security.helper.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Provides protection against directory traversal.
3 | *
4 | * @param {string} filename - The filename to sanitize
5 | * @example
6 | * sanitizeFilename('foo.bar');
7 | *
8 | * @returns {string} - The sanitized filename
9 | */
10 | export const sanitizeFilename = (filename: string): string => {
11 | return filename.replace(/[^a-z0-9.]/gi, '_').toLowerCase();
12 | };
13 |
14 | /**
15 | * Strips HTML tags from a string.
16 | *
17 | * @param {string} html - The HTML to strip
18 | * @example
19 | * stripHtmlTags('
foo
');
20 | *
21 | * @returns {string} - The stripped HTML
22 | */
23 | export const stripHtmlTags = (html: string): string => {
24 | return html.replace(/<[^>]*>/g, '');
25 | };
26 |
27 | /**
28 | * Escapes a string for use in HTML.
29 | * @param {string} str - The string to escape
30 | * @example
31 | * escapeHtml('
foo
');
32 | *
33 | * @returns {string} - The escaped string
34 | */
35 | export const escapeHtml = (str: string): string => {
36 | return str.replace(//g, '>');
37 | };
38 |
39 | /**
40 | * Escapes a string for use in JavaScript.
41 | * @param {string} str - The string to escape
42 | * @example
43 | * escapeJs('foo "bar"');
44 | *
45 | * @returns {string} - The escaped string
46 | */
47 | export const escapeJs = (str: string): string => {
48 | return str.replace(/'/g, "\\'").replace(/"/g, '\\"');
49 | };
50 |
51 | /**
52 | * Escapes a string for use in a URL.
53 | *
54 | * @param {string} str - The string to escape
55 | * @example
56 | * escapeUrl('foo bar');
57 | *
58 | * @returns {string} - The escaped string
59 | */
60 | export const escapeUrl = (str: string): string => {
61 | return encodeURIComponent(str);
62 | };
63 |
64 | /**
65 | * Escapes a string for use in a regular expression.
66 | *
67 | * @param {string} str - The string to escape
68 | * @example
69 | * escapeRegExp('foo.bar');
70 | *
71 | * @returns {string} - The escaped string
72 | */
73 | export const escapeRegExp = (str: string): string => {
74 | return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
75 | };
76 |
77 | /**
78 | * Returns a random nonce.
79 | *
80 | * @example
81 | * const nonce = getNonce();
82 | *
83 | * @returns {string} - The nonce
84 | */
85 | export const getNonce = () => {
86 | let text = '';
87 | const possible =
88 | 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
89 | for (let i = 0; i < 32; i++) {
90 | text += possible.charAt(Math.floor(Math.random() * possible.length));
91 | }
92 | return text;
93 | };
94 |
--------------------------------------------------------------------------------
/src/app/helpers/tree.helper.ts:
--------------------------------------------------------------------------------
1 | import { Tree } from '../interfaces';
2 |
3 | export const generateTree = (
4 | json: object,
5 | showValues: boolean = true,
6 | ): Tree => {
7 | const tree: Tree = {};
8 | let currentId = 1;
9 |
10 | // Initialize the queue with the root node
11 | const queue: { id: number; name: string; data: unknown }[] = [
12 | { id: currentId, name: 'root', data: json },
13 | ];
14 |
15 | // Process each item in the queue
16 | while (queue.length > 0) {
17 | const { id, name, data } = queue.shift()!;
18 |
19 | // Create the current node and add it to the tree
20 | tree[id] = { id: id.toString(), name };
21 |
22 | // Determine if the node has children
23 | if (typeof data === 'object' && data !== null) {
24 | const children: number[] = [];
25 |
26 | // Add each property or array item to the queue
27 | for (const [key, value] of Object.entries(data)) {
28 | currentId += 1;
29 | children.push(currentId);
30 |
31 | // Add to the queue with an incremented ID
32 | queue.push({ id: currentId, name: key, data: value });
33 | }
34 |
35 | tree[id].children = children;
36 | } else if (showValues) {
37 | // If it's a primitive value and showValues is true, add it as a leaf node
38 | currentId += 1;
39 | tree[currentId] = { id: currentId.toString(), name: data.toString() };
40 | tree[id].children = [currentId];
41 | }
42 | }
43 |
44 | return tree;
45 | };
46 |
--------------------------------------------------------------------------------
/src/app/interfaces/index.ts:
--------------------------------------------------------------------------------
1 | export * from './tree.interface';
2 |
--------------------------------------------------------------------------------
/src/app/interfaces/tree.interface.ts:
--------------------------------------------------------------------------------
1 | export interface TreeNode {
2 | id: string;
3 | name: string;
4 | children?: number[];
5 | }
6 |
7 | export interface Tree {
8 | [key: number]: TreeNode;
9 | }
10 |
--------------------------------------------------------------------------------
/src/app/models/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelGil/vscode-json-flow/d6515cd6b0259e893793e999deafcef49df6082f/src/app/models/.gitkeep
--------------------------------------------------------------------------------
/src/app/models/index.ts:
--------------------------------------------------------------------------------
1 | export * from './node.model';
2 |
--------------------------------------------------------------------------------
/src/app/models/node.model.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Command,
3 | ThemeIcon,
4 | TreeItem,
5 | TreeItemCollapsibleState,
6 | TreeItemLabel,
7 | Uri,
8 | } from 'vscode';
9 |
10 | /**
11 | * The Node class
12 | *
13 | * @class
14 | * @classdesc The class that represents a node in the tree view.
15 | * @export
16 | * @public
17 | * @extends {TreeItem}
18 | * @property {string | TreeItemLabel} label - The label
19 | * @property {string | Uri | { light: Uri; dark: Uri } | ThemeIcon} [iconPath] - The icon path
20 | * @property {Command} [command] - The command
21 | * @property {Uri} [resourceUri] - The resource URI
22 | * @property {string} [contextValue] - The context value
23 | * @property {Node[]} [children] - The children
24 | * @example
25 | * const node = new Node('About Us', TreeItemCollapsibleState.None, 'about', {
26 | * title: 'About Us',
27 | * command: 'extension-stater-kit.aboutUs',
28 | * });
29 | *
30 | * @see https://code.visualstudio.com/api/references/vscode-api#TreeItem
31 | */
32 | export class NodeModel extends TreeItem {
33 | // -----------------------------------------------------------------
34 | // Properties
35 | // -----------------------------------------------------------------
36 |
37 | // Public properties
38 | /**
39 | * The children.
40 | * @type {NodeModel[]}
41 | * @public
42 | * @memberof NodeModel
43 | * @example
44 | * node.children = [];
45 | */
46 | children?: NodeModel[];
47 |
48 | // -----------------------------------------------------------------
49 | // Constructor
50 | // -----------------------------------------------------------------
51 |
52 | /**
53 | * The constructor
54 | *
55 | * @constructor
56 | * @param {string | TreeItemLabel} label - The label
57 | * @param {string | Uri | { light: Uri; dark: Uri } | ThemeIcon} [iconPath] - The icon path
58 | * @param {Command} [command] - The command
59 | * @param {Uri} [resourceUri] - The resource URI
60 | * @param {string} [contextValue] - The context value
61 | * @param {NodeModel[]} [children] - The children
62 | * @example
63 | * const node = new Node('About Us', new ThemeIcon('info'), {
64 | * title: 'About Us',
65 | * command: 'extension-stater-kit.aboutUs',
66 | * });
67 | */
68 | constructor(
69 | readonly label: string | TreeItemLabel,
70 | readonly iconPath?: string | Uri | { light: Uri; dark: Uri } | ThemeIcon,
71 | readonly command?: Command,
72 | readonly resourceUri?: Uri,
73 | readonly contextValue?: string,
74 | children?: NodeModel[],
75 | ) {
76 | super(
77 | label,
78 | children
79 | ? TreeItemCollapsibleState.Expanded
80 | : TreeItemCollapsibleState.None,
81 | );
82 | this.iconPath = iconPath;
83 | this.resourceUri = resourceUri;
84 | this.command = command;
85 | this.contextValue = contextValue;
86 | this.children = children;
87 | }
88 |
89 | // -----------------------------------------------------------------
90 | // Methods
91 | // -----------------------------------------------------------------
92 |
93 | // Public methods
94 | /**
95 | * The setChildren method
96 | *
97 | * @function setChildren
98 | * @param {NodeModel[]} children - The children
99 | * @public
100 | * @memberof NodeModel
101 | * @example
102 | * node.setChildren([]);
103 | *
104 | * @returns {void} The result
105 | */
106 | setChildren(children: NodeModel[]): void {
107 | this.collapsibleState = TreeItemCollapsibleState.Expanded;
108 | this.children = children;
109 | }
110 |
111 | /**
112 | * The hasChildren method
113 | *
114 | * @function hasChildren
115 | * @public
116 | * @memberof NodeModel
117 | * @example
118 | * const hasChildren = node.hasChildren();
119 | *
120 | * @returns {boolean} The result
121 | */
122 | hasChildren(): boolean {
123 | return !!(this.children && this.children.length);
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/src/app/providers/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelGil/vscode-json-flow/d6515cd6b0259e893793e999deafcef49df6082f/src/app/providers/.gitkeep
--------------------------------------------------------------------------------
/src/app/providers/feedback.provider.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Event,
3 | EventEmitter,
4 | l10n,
5 | ProviderResult,
6 | ThemeIcon,
7 | TreeDataProvider,
8 | TreeItem,
9 | } from 'vscode';
10 |
11 | import { EXTENSION_ID } from '../configs';
12 | import { FeedbackController } from '../controllers';
13 | import { NodeModel } from '../models';
14 |
15 | /**
16 | * The FeedbackProvider class
17 | *
18 | * @class
19 | * @classdesc The class that represents the feedback provider.
20 | * @export
21 | * @public
22 | * @implements {TreeDataProvider}
23 | * @property {EventEmitter} _onDidChangeTreeData - The onDidChangeTreeData event emitter
24 | * @property {Event} onDidChangeTreeData - The onDidChangeTreeData event
25 | * @property {FeedbackController} controller - The feedback controller
26 | * @example
27 | * const provider = new FeedbackProvider();
28 | *
29 | * @see https://code.visualstudio.com/api/references/vscode-api#TreeDataProvider
30 | */
31 | export class FeedbackProvider implements TreeDataProvider {
32 | // -----------------------------------------------------------------
33 | // Properties
34 | // -----------------------------------------------------------------
35 |
36 | // Public properties
37 | /**
38 | * The onDidChangeTreeData event.
39 | * @type {Event}
40 | * @public
41 | * @memberof FeedbackProvider
42 | * @example
43 | * readonly onDidChangeTreeData: Event;
44 | * this.onDidChangeTreeData = this._onDidChangeTreeData.event;
45 | *
46 | * @see https://code.visualstudio.com/api/references/vscode-api#Event
47 | */
48 | readonly onDidChangeTreeData: Event;
49 |
50 | // Private properties
51 | /**
52 | * The onDidChangeTreeData event emitter.
53 | * @type {EventEmitter}
54 | * @private
55 | * @memberof FeedbackProvider
56 | * @example
57 | * this._onDidChangeTreeData = new EventEmitter();
58 | * this.onDidChangeTreeData = this._onDidChangeTreeData.event;
59 | *
60 | * @see https://code.visualstudio.com/api/references/vscode-api#EventEmitter
61 | */
62 | private _onDidChangeTreeData: EventEmitter<
63 | NodeModel | undefined | null | void
64 | >;
65 |
66 | // -----------------------------------------------------------------
67 | // Constructor
68 | // -----------------------------------------------------------------
69 |
70 | /**
71 | * Constructor for the FeedbackProvider class
72 | *
73 | * @constructor
74 | * @public
75 | * @memberof FeedbackProvider
76 | */
77 | constructor(readonly controller: FeedbackController) {
78 | this._onDidChangeTreeData = new EventEmitter<
79 | NodeModel | undefined | null | void
80 | >();
81 | this.onDidChangeTreeData = this._onDidChangeTreeData.event;
82 | }
83 |
84 | // -----------------------------------------------------------------
85 | // Methods
86 | // -----------------------------------------------------------------
87 |
88 | // Public methods
89 | /**
90 | * Returns the tree item for the supplied element.
91 | *
92 | * @function getTreeItem
93 | * @param {NodeModel} element - The element
94 | * @public
95 | * @memberof FeedbackProvider
96 | * @example
97 | * const treeItem = provider.getTreeItem(element);
98 | *
99 | * @returns {TreeItem | Thenable} - The tree item
100 | *
101 | * @see https://code.visualstudio.com/api/references/vscode-api#TreeDataProvider
102 | */
103 | // biome-ignore lint/correctness/noUndeclaredVariables: we dont control vscode's api
104 | getTreeItem(element: NodeModel): TreeItem | Thenable {
105 | return element;
106 | }
107 |
108 | /**
109 | * Returns the children for the supplied element.
110 | *
111 | * @function getChildren
112 | * @param {NodeModel} [element] - The element
113 | * @public
114 | * @memberof FeedbackProvider
115 | * @example
116 | * const children = provider.getChildren(element);
117 | *
118 | * @returns {ProviderResult} - The children
119 | *
120 | * @see https://code.visualstudio.com/api/references/vscode-api#TreeDataProvider
121 | */
122 | getChildren(element?: NodeModel): ProviderResult {
123 | if (element) {
124 | return element.children;
125 | }
126 |
127 | return this.getFeedbacks();
128 | }
129 |
130 | /**
131 | * Refreshes the tree data.
132 | *
133 | * @function refresh
134 | * @public
135 | * @memberof FeedbackProvider
136 | * @example
137 | * provider.refresh();
138 | *
139 | * @returns {void} - No return value
140 | */
141 | refresh(): void {
142 | this._onDidChangeTreeData.fire();
143 | }
144 |
145 | // Private methods
146 | /**
147 | * Returns the feedbacks.
148 | *
149 | * @function getFeedbacks
150 | * @private
151 | * @memberof FeedbackProvider
152 | * @example
153 | * const feedbacks = this.getFeedbacks();
154 | *
155 | * @returns {NodeModel[]} - The feedbacks
156 | */
157 | private getFeedbacks(): NodeModel[] {
158 | return [
159 | new NodeModel(l10n.t('Report Issues'), new ThemeIcon('bug'), {
160 | title: 'Report Issues',
161 | command: `${EXTENSION_ID}.feedback.reportIssues`,
162 | }),
163 | new NodeModel(l10n.t('Rate Us'), new ThemeIcon('star'), {
164 | title: 'Rate Us',
165 | command: `${EXTENSION_ID}.feedback.rateUs`,
166 | }),
167 | ];
168 | }
169 | }
170 |
--------------------------------------------------------------------------------
/src/app/providers/files.providers.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Event,
3 | EventEmitter,
4 | ProviderResult,
5 | ThemeIcon,
6 | TreeDataProvider,
7 | TreeItem,
8 | } from 'vscode';
9 |
10 | import { FilesController } from '../controllers';
11 | import { NodeModel } from '../models';
12 |
13 | /**
14 | * The FilesProvider class
15 | *
16 | * @class
17 | * @classdesc The class that represents the files provider.
18 | * @export
19 | * @public
20 | * @implements {TreeDataProvider}
21 | * @property {EventEmitter} _onDidChangeTreeData - The onDidChangeTreeData event emitter
22 | * @property {Event} onDidChangeTreeData - The onDidChangeTreeData event
23 | * @property {filesController} controller - The files controller
24 | * @example
25 | * const provider = new FilesProvider();
26 | *
27 | * @see https://code.visualstudio.com/api/references/vscode-api#TreeDataProvider
28 | */
29 | export class FilesProvider implements TreeDataProvider {
30 | // -----------------------------------------------------------------
31 | // Properties
32 | // -----------------------------------------------------------------
33 |
34 | // Public properties
35 | /**
36 | * The onDidChangeTreeData event.
37 | * @type {Event}
38 | * @public
39 | * @memberof FilesProvider
40 | * @example
41 | * readonly onDidChangeTreeData: Event;
42 | * this.onDidChangeTreeData = this._onDidChangeTreeData.event;
43 | *
44 | * @see https://code.visualstudio.com/api/references/vscode-api#Event
45 | */
46 | readonly onDidChangeTreeData: Event;
47 |
48 | // Private properties
49 | /**
50 | * The onDidChangeTreeData event emitter.
51 | * @type {EventEmitter}
52 | * @private
53 | * @memberof FilesProvider
54 | * @example
55 | * this._onDidChangeTreeData = new EventEmitter();
56 | * this.onDidChangeTreeData = this._onDidChangeTreeData.event;
57 | *
58 | * @see https://code.visualstudio.com/api/references/vscode-api#EventEmitter
59 | */
60 | private _onDidChangeTreeData: EventEmitter<
61 | NodeModel | undefined | null | void
62 | >;
63 |
64 | // -----------------------------------------------------------------
65 | // Constructor
66 | // -----------------------------------------------------------------
67 |
68 | /**
69 | * Constructor for the FilesProvider class
70 | *
71 | * @constructor
72 | * @public
73 | * @memberof FilesProvider
74 | */
75 | constructor(readonly controller: FilesController) {
76 | this._onDidChangeTreeData = new EventEmitter<
77 | NodeModel | undefined | null | void
78 | >();
79 | this.onDidChangeTreeData = this._onDidChangeTreeData.event;
80 | }
81 |
82 | // -----------------------------------------------------------------
83 | // Methods
84 | // -----------------------------------------------------------------
85 |
86 | // Public methods
87 | /**
88 | * Returns the tree item for the supplied element.
89 | *
90 | * @function getTreeItem
91 | * @param {NodeModel} element - The element
92 | * @public
93 | * @memberof FilesProvider
94 | * @example
95 | * const treeItem = provider.getTreeItem(element);
96 | *
97 | * @returns {TreeItem | Thenable} - The tree item
98 | *
99 | * @see https://code.visualstudio.com/api/references/vscode-api#TreeDataProvider
100 | */
101 | // biome-ignore lint/correctness/noUndeclaredVariables: we dont control vscode's api
102 | getTreeItem(element: NodeModel): TreeItem | Thenable {
103 | return element;
104 | }
105 |
106 | /**
107 | * Returns the children for the supplied element.
108 | *
109 | * @function getChildren
110 | * @param {NodeModel} [element] - The element
111 | * @public
112 | * @memberof FilesProvider
113 | * @example
114 | * const children = provider.getChildren(element);
115 | *
116 | * @returns {ProviderResult} - The children
117 | *
118 | * @see https://code.visualstudio.com/api/references/vscode-api#TreeDataProvider
119 | */
120 | getChildren(element?: NodeModel): ProviderResult {
121 | if (element) {
122 | return element.children;
123 | }
124 |
125 | return this.getListFiles();
126 | }
127 |
128 | /**
129 | * Refreshes the tree data.
130 | *
131 | * @function refresh
132 | * @public
133 | * @memberof FeedbackProvider
134 | * @example
135 | * provider.refresh();
136 | *
137 | * @returns {void} - No return value
138 | */
139 | refresh(): void {
140 | this._onDidChangeTreeData.fire();
141 | }
142 |
143 | // Private methods
144 | /**
145 | * Gets the list of files.
146 | *
147 | * @function getListFiles
148 | * @private
149 | * @memberof FilesProvider
150 | * @example
151 | * const files = provider.getListFiles();
152 | *
153 | * @returns {Promise} - The list of files
154 | */
155 | private async getListFiles(): Promise {
156 | const files = await this.controller.getFiles();
157 |
158 | if (!files) {
159 | return;
160 | }
161 |
162 | const nodes: NodeModel[] = [];
163 |
164 | const fileTypes = this.controller.config.include;
165 |
166 | for (const fileType of fileTypes) {
167 | const children = files.filter((file) =>
168 | file.label.toString().includes(`.${fileType}`),
169 | );
170 |
171 | if (children.length !== 0) {
172 | const node = new NodeModel(
173 | `${fileType}: ${children.length}`,
174 | new ThemeIcon('folder-opened'),
175 | undefined,
176 | undefined,
177 | fileType,
178 | children,
179 | );
180 |
181 | nodes.push(node);
182 | }
183 | }
184 |
185 | if (nodes.length === 0) {
186 | return;
187 | }
188 |
189 | return nodes;
190 | }
191 | }
192 |
--------------------------------------------------------------------------------
/src/app/providers/index.ts:
--------------------------------------------------------------------------------
1 | export * from './feedback.provider';
2 | export * from './files.providers';
3 | export * from './json.provider';
4 |
--------------------------------------------------------------------------------
/src/app/providers/json.provider.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Disposable,
3 | Uri,
4 | ViewColumn,
5 | Webview,
6 | WebviewOptions,
7 | WebviewPanel,
8 | window,
9 | } from 'vscode';
10 |
11 | import { EXTENSION_ID } from '../configs';
12 | import { JsonController } from '../controllers';
13 | import { getNonce } from '../helpers';
14 |
15 | /**
16 | * The JSONProvider class.
17 | *
18 | * @class
19 | * @classdesc The class that represents the json provider.
20 | * @export
21 | * @public
22 | * @property {string} static viewType - The view type
23 | * @property {WebviewView} [_view] - The view
24 | * @property {OpenAIService} [openAISservice] - The OpenAI service
25 | * @example
26 | * const provider = new JSONProvider(extensionUri);
27 | */
28 | export class JSONProvider {
29 | // -----------------------------------------------------------------
30 | // Properties
31 | // -----------------------------------------------------------------
32 |
33 | // Public properties
34 | /**
35 | * The current provider.
36 | *
37 | * @public
38 | * @static
39 | * @memberof JSONProvider
40 | * @type {JSONProvider | undefined}
41 | */
42 | static currentProvider: JSONProvider | undefined;
43 |
44 | /**
45 | * The view type.
46 | *
47 | * @public
48 | * @static
49 | * @memberof JSONProvider
50 | * @type {string}
51 | */
52 | static readonly viewType: string = `${EXTENSION_ID}.jsonView`;
53 |
54 | // Private properties
55 | /**
56 | * The disposables.
57 | *
58 | * @private
59 | * @memberof JSONProvider
60 | * @type {Disposable[]}
61 | */
62 | private _disposables: Disposable[] = [];
63 |
64 | // -----------------------------------------------------------------
65 | // Constructor
66 | // -----------------------------------------------------------------
67 |
68 | /**
69 | * Constructor for the JSONProvider class.
70 | *
71 | * @constructor
72 | * @param {WebviewPanel} _panel - The webview panel
73 | * @param {Uri} _extensionUri - The extension URI
74 | * @public
75 | * @memberof JSONProvider
76 | */
77 | private constructor(
78 | private readonly _panel: WebviewPanel,
79 | private readonly _extensionUri: Uri,
80 | ) {
81 | this._update();
82 |
83 | this._panel.onDidDispose(() => this.dispose(), null, this._disposables);
84 |
85 | this._panel.webview.onDidReceiveMessage(
86 | (message) => {
87 | switch (message.type) {
88 | case 'onSaveImage':
89 | JsonController.saveImage(message.data);
90 | break;
91 |
92 | default:
93 | break;
94 | }
95 | },
96 | null,
97 | this._disposables,
98 | );
99 |
100 | this._panel.onDidChangeViewState(
101 | () => {
102 | if (this._panel.visible) {
103 | this._update();
104 | }
105 | },
106 | null,
107 | this._disposables,
108 | );
109 | }
110 |
111 | // -----------------------------------------------------------------
112 | // Methods
113 | // -----------------------------------------------------------------
114 |
115 | // Public methods
116 | /**
117 | * The createPanel method.
118 | *
119 | * @function createPanel
120 | * @param {Uri} extensionUri - The extension URI
121 | * @param {Uri} json - The JSON URI
122 | * @public
123 | * @static
124 | * @memberof JSONProvider
125 | * @example
126 | * JSONProvider.createPanel(extensionUri);
127 | *
128 | * @returns {WebviewPanel}
129 | */
130 | static createPanel(extensionUri: Uri): WebviewPanel {
131 | if (JSONProvider.currentProvider) {
132 | JSONProvider.currentProvider._panel.webview.postMessage({
133 | type: 'clearJson',
134 | });
135 |
136 | JSONProvider.currentProvider._panel.reveal(ViewColumn.One);
137 |
138 | return JSONProvider.currentProvider._panel;
139 | }
140 |
141 | const panel = window.createWebviewPanel(
142 | JSONProvider.viewType,
143 | 'JSON Flow',
144 | ViewColumn.One,
145 | this.getWebviewOptions(extensionUri),
146 | );
147 |
148 | JSONProvider.currentProvider = new JSONProvider(panel, extensionUri);
149 |
150 | return panel;
151 | }
152 |
153 | /**
154 | * The getWebviewOptions method.
155 | *
156 | * @function getWebviewOptions
157 | * @param {Uri} extensionUri - The extension URI
158 | * @public
159 | * @static
160 | * @memberof JSONProvider
161 | * @example
162 | * const options = JSONProvider.getWebviewOptions(extensionUri);
163 | *
164 | * @returns {WebviewOptions} - The webview options
165 | */
166 | static getWebviewOptions(extensionUri: Uri): WebviewOptions {
167 | return {
168 | enableScripts: true,
169 | localResourceRoots: [Uri.joinPath(extensionUri, './out/webview')],
170 | };
171 | }
172 |
173 | /**
174 | * The revive method.
175 | *
176 | * @function revive
177 | * @param {WebviewPanel} panel - The webview panel
178 | * @param {Uri} extensionUri - The extension URI
179 | * @public
180 | * @static
181 | * @memberof JSONProvider
182 | * @example
183 | * JSONProvider.revive(panel, extensionUri);
184 | *
185 | * @returns {void}
186 | */
187 | static revive(panel: WebviewPanel, extensionUri: Uri): void {
188 | JSONProvider.currentProvider = new JSONProvider(panel, extensionUri);
189 | }
190 |
191 | /**
192 | * The dispose method.
193 | *
194 | * @function dispose
195 | * @public
196 | * @memberof JSONProvider
197 | * @example
198 | * provider.dispose();
199 | *
200 | * @returns {void}
201 | */
202 | dispose() {
203 | JSONProvider.currentProvider = undefined;
204 |
205 | this._panel.dispose();
206 |
207 | while (this._disposables.length) {
208 | const x = this._disposables.pop();
209 | if (x) {
210 | x.dispose();
211 | }
212 | }
213 | }
214 |
215 | // Private methods
216 | /**
217 | * The _update method.
218 | *
219 | * @function _update
220 | * @private
221 | * @memberof JSONProvider
222 | * @example
223 | * provider._update();
224 | *
225 | * @returns {void}
226 | */
227 | private _update(): void {
228 | const webview = this._panel.webview;
229 |
230 | this._panel.webview.html = this._getHtmlForWebview(webview);
231 | }
232 |
233 | /**
234 | * The _getHtmlForWebview method.
235 | *
236 | * @function _getHtmlForWebview
237 | * @param {Webview} webview - The webview
238 | * @private
239 | * @memberof JSONProvider
240 | * @example
241 | * const html = provider._getHtmlForWebview(webview);
242 | *
243 | * @returns {string} - The HTML for the webview
244 | */
245 | private _getHtmlForWebview(webview: Webview): string {
246 | // Get the local path to main script run in the webview, then convert it to a uri we can use in the webview.
247 | const scriptUri = webview.asWebviewUri(
248 | Uri.joinPath(this._extensionUri, './out/webview', 'main.js'),
249 | );
250 |
251 | // Do the same for the stylesheet.
252 | const styleMainUri = webview.asWebviewUri(
253 | Uri.joinPath(this._extensionUri, './out/webview', 'main.css'),
254 | );
255 |
256 | // Use a nonce to only allow a specific script to be run.
257 | const nonce = getNonce();
258 |
259 | return `
260 |
261 |
262 |
263 |
264 |
269 |
274 |
275 |
276 |
277 |
278 |
279 | JSON Flow
280 |
281 |
282 |
283 |
284 |
297 |
298 |
299 | `;
300 | }
301 | }
302 |
--------------------------------------------------------------------------------
/src/test/extension.test.ts:
--------------------------------------------------------------------------------
1 | import * as assert from 'assert';
2 |
3 | // You can import and use all API from the 'vscode' module
4 | // as well as import your extension to test it
5 | import * as vscode from 'vscode';
6 | // import * as myExtension from '../../extension';
7 |
8 | suite('Extension Test Suite', () => {
9 | vscode.window.showInformationMessage('Start all tests.');
10 |
11 | test('Sample test', () => {
12 | assert.strictEqual(-1, [1, 2, 3].indexOf(5));
13 | assert.strictEqual(-1, [1, 2, 3].indexOf(0));
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | export default {
3 | content: ['./index.html', './webview/**/*.{js,ts,jsx,tsx}'],
4 | theme: {
5 | extend: {},
6 | },
7 | plugins: [],
8 | };
9 |
--------------------------------------------------------------------------------
/tsconfig.doc.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": [
3 | "src/**/*.ts",
4 | "webview/**/*.{ts,tsx}",
5 | ],
6 | "exclude": [
7 | "src/test/**/*.ts"
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "NodeNext",
4 | "target": "ES2021",
5 | "outDir": "out",
6 | "lib": ["ES2021", "DOM"],
7 | "sourceMap": true,
8 | "rootDir": "src",
9 | /* Linting */
10 | "strict": false /* enable all strict type-checking options */,
11 | /* Additional Checks */
12 | "noImplicitReturns": false /* Report error when not all code paths in function return a value. */,
13 | "noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */,
14 | "noUnusedParameters": true /* Report errors on unused parameters. */
15 | },
16 | "include": ["src/**/*"],
17 | "exclude": ["node_modules", ".vscode-test"]
18 | }
19 |
--------------------------------------------------------------------------------
/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "skipLibCheck": true,
5 | "module": "ESNext",
6 | "moduleResolution": "bundler",
7 | "allowSyntheticDefaultImports": true,
8 | "strict": true
9 | },
10 | "include": ["vite.config.ts"]
11 | }
12 |
--------------------------------------------------------------------------------
/tsconfig.web.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "ESNext",
4 | "target": "ES2021",
5 | "lib": [
6 | "ES2021",
7 | "DOM",
8 | "DOM.Iterable"
9 | ],
10 | "sourceMap": true,
11 | "rootDir": "webview",
12 | "useDefineForClassFields": true,
13 | "skipLibCheck": true,
14 | /* Bundler mode */
15 | "moduleResolution": "bundler",
16 | "allowImportingTsExtensions": true,
17 | "resolveJsonModule": true,
18 | "isolatedModules": true,
19 | "noEmit": true,
20 | "jsx": "react-jsx",
21 | /* Linting */
22 | "strict": true /* enable all strict type-checking options */,
23 | "baseUrl": "./webview",
24 | "paths": {
25 | "*": [
26 | "types/*"
27 | ]
28 | }
29 | },
30 | "include": [
31 | "webview/**/*"
32 | ],
33 | "exclude": [
34 | "node_modules"
35 | ],
36 | "references": [
37 | {
38 | "path": "./tsconfig.node.json"
39 | }
40 | ]
41 | }
--------------------------------------------------------------------------------
/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | build: {
8 | minify: true,
9 | rollupOptions: {
10 | output: {
11 | entryFileNames: 'main.js',
12 | assetFileNames: 'main.css',
13 | },
14 | },
15 | },
16 | });
17 |
--------------------------------------------------------------------------------
/vsc-extension-quickstart.md:
--------------------------------------------------------------------------------
1 | # Welcome to your VS Code Extension
2 |
3 | ## What's in the folder
4 |
5 | - This folder contains all of the files necessary for your extension.
6 | - `package.json` - this is the manifest file in which you declare your extension and command.
7 | - The sample plugin registers a command and defines its title and command name. With this information VS Code can show the command in the command palette. It doesn’t yet need to load the plugin.
8 | - `src/extension.ts` - this is the main file where you will provide the implementation of your command.
9 | - The file exports one function, `activate`, which is called the very first time your extension is activated (in this case by executing the command). Inside the `activate` function we call `registerCommand`.
10 | - We pass the function containing the implementation of the command as the second parameter to `registerCommand`.
11 |
12 | ## Get up and running straight away
13 |
14 | - Press `F5` to open a new window with your extension loaded.
15 | - Run your command from the command palette by pressing (`Ctrl+Shift+P` or `Cmd+Shift+P` on Mac) and typing `Hello World`.
16 | - Set breakpoints in your code inside `src/extension.ts` to debug your extension.
17 | - Find output from your extension in the debug console.
18 |
19 | ## Make changes
20 |
21 | - You can relaunch the extension from the debug toolbar after changing code in `src/extension.ts`.
22 | - You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes.
23 |
24 | ## Explore the API
25 |
26 | - You can open the full set of our API when you open the file `node_modules/@types/vscode/index.d.ts`.
27 |
28 | ## Run tests
29 |
30 | - Open the debug viewlet (`Ctrl+Shift+D` or `Cmd+Shift+D` on Mac) and from the launch configuration dropdown pick `Extension Tests`.
31 | - Press `F5` to run the tests in a new window with your extension loaded.
32 | - See the output of the test result in the debug console.
33 | - Make changes to `src/test/suite/extension.test.ts` or create new test files inside the `test/suite` folder.
34 | - The provided test runner will only consider files matching the name pattern `**.test.ts`.
35 | - You can create folders inside the `test` folder to structure your tests any way you want.
36 |
37 | ## Go further
38 |
39 | - Reduce the extension size and improve the startup time by [bundling your extension](https://code.visualstudio.com/api/working-with-extensions/bundling-extension).
40 | - [Publish your extension](https://code.visualstudio.com/api/working-with-extensions/publishing-extension) on the VSCode extension marketplace.
41 | - Automate builds by setting up [Continuous Integration](https://code.visualstudio.com/api/working-with-extensions/continuous-integration).
42 |
--------------------------------------------------------------------------------
/webview/App.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Background,
3 | Connection,
4 | ConnectionLineType,
5 | Controls,
6 | Edge,
7 | MiniMap,
8 | Node,
9 | Panel,
10 | ReactFlow,
11 | addEdge,
12 | useEdgesState,
13 | useNodesState,
14 | } from '@xyflow/react';
15 | import '@xyflow/react/dist/style.css';
16 | import * as htmlToImage from 'html-to-image';
17 | import { useCallback, useEffect, useRef, useState } from 'react';
18 | import { Direction, StateType } from './common';
19 | import CustomNode from './components/CustomNode';
20 | import Loading from './components/Loading';
21 | import { layoutElements } from './components/layout-elements';
22 |
23 | // @ts-ignore
24 | // biome-ignore lint/correctness/noUndeclaredVariables: vscode is a global variable
25 | const vscode = acquireVsCodeApi();
26 |
27 | const nodeTypes = {
28 | custom: CustomNode,
29 | };
30 |
31 | const LayoutFlow = () => {
32 | const jsonState: StateType = vscode.getState();
33 | const [json, setJson] = useState(jsonState?.json ?? null);
34 | const [layoutDirection, setLayoutDirection] = useState(
35 | jsonState?.layoutDirection ?? 'TB'
36 | );
37 | const [nodes, setNodes, onNodesChange] = useNodesState([]);
38 | const [edges, setEdges, onEdgesChange] = useEdgesState([]);
39 | const flowContainerRef = useRef(null);
40 |
41 | useEffect(() => {
42 | const handleMessage = (event: MessageEvent) => {
43 | const message = event.data;
44 |
45 | switch (message.type) {
46 | case 'clearJson': {
47 | setJson(null);
48 | vscode.setState(null);
49 | break;
50 | }
51 |
52 | case 'setJson': {
53 | setJson(message.data);
54 | setLayoutDirection(message.layoutDirection);
55 | vscode.setState({
56 | ...vscode.getState(),
57 | json: message.data,
58 | layoutDirection: message.layoutDirection,
59 | });
60 | break;
61 | }
62 |
63 | default: {
64 | break;
65 | }
66 | }
67 | };
68 |
69 | window.addEventListener('message', handleMessage);
70 | return () => window.removeEventListener('message', handleMessage);
71 | }, []);
72 |
73 | useEffect(() => {
74 | if (json) {
75 | const treeRootId = 1;
76 | const { nodes: layoutedNodes, edges: layoutedEdges } = layoutElements(
77 | json,
78 | treeRootId,
79 | layoutDirection
80 | );
81 | setNodes(layoutedNodes);
82 | setEdges(layoutedEdges);
83 | }
84 | }, [json, layoutDirection, setNodes, setEdges]);
85 |
86 | const onConnect = useCallback(
87 | (params: Connection) =>
88 | setEdges((eds) =>
89 | addEdge(
90 | { ...params, type: ConnectionLineType.SmoothStep, animated: true },
91 | eds
92 | )
93 | ),
94 | [setEdges]
95 | );
96 |
97 | const onLayout = useCallback(
98 | (direction: Direction) => {
99 | if (!json) {
100 | return;
101 | }
102 |
103 | setLayoutDirection(direction);
104 | vscode.setState({
105 | ...vscode.getState(),
106 | layoutDirection: direction,
107 | });
108 |
109 | const treeRootId = 1;
110 | const { nodes: layoutedNodes, edges: layoutedEdges } = layoutElements(
111 | json,
112 | treeRootId,
113 | direction
114 | );
115 |
116 | setNodes([...layoutedNodes]);
117 | setEdges([...layoutedEdges]);
118 | },
119 | [json, setNodes, setEdges]
120 | );
121 |
122 | const handleSaveImage = async () => {
123 | if (flowContainerRef.current) {
124 | try {
125 | // Temporarily hide the controls
126 | const controls = flowContainerRef.current.querySelectorAll(
127 | '.react-flow__panel, .react-flow__controls, .react-flow__minimap, .react-flow__background'
128 | );
129 | controls.forEach((control) => {
130 | (control as HTMLElement).style.display = 'none';
131 | });
132 |
133 | const dataUrl = await htmlToImage.toPng(flowContainerRef.current);
134 |
135 | // Show the controls again
136 | controls.forEach((control) => {
137 | (control as HTMLElement).style.display = 'block';
138 | });
139 |
140 | // Send the generated image to the VS Code extension
141 | vscode.postMessage({ type: 'onSaveImage', data: dataUrl });
142 | } catch (error) {
143 | console.error('Error generating image:', error);
144 | }
145 | }
146 | };
147 |
148 | if (!json) {
149 | return ;
150 | }
151 |
152 | return (
153 |