├── .eslintrc.json
├── .gitignore
├── .vscode
├── extensions.json
├── launch.json
├── settings.json
└── tasks.json
├── .vscodeignore
├── CHANGELOG.md
├── README.md
├── json
├── demo.json
└── root.json
├── media
├── gifs
│ ├── Tree.gif
│ └── Upload.gif
├── mv-logo.png
├── mv.svg
├── reset.css
└── vscode.css
├── package.json
├── src
├── MVParser.ts
├── SidebarProvider.ts
├── extension.ts
├── getNonce.ts
├── helpers
│ └── parserHelpers.js
├── test
│ ├── runTest.ts
│ └── suite
│ │ ├── extension.test.ts
│ │ └── index.ts
├── types
│ ├── Imports.ts
│ └── Tree.ts
└── webviews
│ ├── components
│ ├── App.vue
│ ├── MVTree.vue
│ └── Tree.vue
│ ├── globals.d.ts
│ ├── img
│ └── logo.png
│ ├── pages
│ └── App.js
│ ├── tsconfig.views.json
│ └── webpack.views.config.js
├── tsconfig.json
├── vsc-extension-quickstart.md
└── webpack.config.js
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "parser": "@typescript-eslint/parser",
4 | "parserOptions": {
5 | "ecmaVersion": 6,
6 | "sourceType": "module"
7 | },
8 | "plugins": [
9 | "@typescript-eslint"
10 | ],
11 | "rules": {
12 | "@typescript-eslint/naming-convention": "warn",
13 | "@typescript-eslint/semi": "warn",
14 | "curly": "warn",
15 | "eqeqeq": "warn",
16 | "no-throw-literal": "warn",
17 | "semi": "off"
18 | },
19 | "ignorePatterns": [
20 | "out",
21 | "dist",
22 | "**/*.d.ts"
23 | ]
24 | }
25 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | out
2 | dist
3 | node_modules
4 | .vscode-test/
5 | *.vsix
6 | .DS_Store
7 | package-lock.json
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | // See http://go.microsoft.com/fwlink/?LinkId=827846
3 | // for the documentation about the extensions.json format
4 | "recommendations": ["dbaeumer.vscode-eslint", "amodio.tsl-problem-matcher"]
5 | }
6 |
--------------------------------------------------------------------------------
/.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}/dist/**/*.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/**/*.js",
30 | "${workspaceFolder}/dist/**/*.js"
31 | ],
32 | "preLaunchTask": "tasks: watch-tests"
33 | }
34 | ]
35 | }
36 |
--------------------------------------------------------------------------------
/.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 | "dist": false // set this to true to hide the "dist" folder with the compiled JS files
6 | },
7 | "search.exclude": {
8 | "out": true, // set this to false to include "out" folder in search results
9 | "dist": true // set this to false to include "dist" folder in search results
10 | },
11 | // Turn off tsc task auto detection since we have the necessary tasks as npm scripts
12 | "typescript.tsc.autoDetect": "off"
13 | }
--------------------------------------------------------------------------------
/.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": [
10 | "$ts-webpack-watch",
11 | "$tslint-webpack-watch"
12 | ],
13 | "isBackground": true,
14 | "presentation": {
15 | "reveal": "never",
16 | "group": "watchers"
17 | },
18 | "group": {
19 | "kind": "build",
20 | "isDefault": true
21 | }
22 | },
23 | {
24 | "type": "npm",
25 | "script": "watch-tests",
26 | "problemMatcher": "$tsc-watch",
27 | "isBackground": true,
28 | "presentation": {
29 | "reveal": "never",
30 | "group": "watchers"
31 | },
32 | "group": "build"
33 | },
34 | {
35 | "label": "tasks: watch-tests",
36 | "dependsOn": [
37 | "npm: watch",
38 | "npm: watch-tests"
39 | ],
40 | "problemMatcher": []
41 | }
42 | ]
43 | }
--------------------------------------------------------------------------------
/.vscodeignore:
--------------------------------------------------------------------------------
1 | .vscode/**
2 | .vscode-test/**
3 | out/**
4 | node_modules/**
5 | src/**
6 | .gitignore
7 | .yarnrc
8 | webpack.config.js
9 | vsc-extension-quickstart.md
10 | **/tsconfig.json
11 | **/.eslintrc.json
12 | **/*.map
13 | **/*.ts
14 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to the "mountainvue" extension will be documented in this file.
4 |
5 | Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
6 |
7 | ## [Unreleased]
8 |
9 | - Initial release
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
12 | [![Contributors][contributors-shield]][contributors-url]
13 | [![Forks][forks-shield]][forks-url]
14 | [![Stargazers][stars-shield]][stars-url]
15 | [![Issues][issues-shield]][issues-url]
16 |
17 | [![LinkedIn][linkedin-shield]][linkedin-url]
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
MountainVue
29 |
30 |
31 | A developer tool to traverse your Vue component tree
32 |
33 |
34 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | Table of Contents
49 |
50 |
51 | About MountainVue
52 |
53 |
54 | Built With
55 |
56 |
57 | Installation
58 |
59 | Usage
60 | Roadmap
61 | Contributing
62 | License
63 | Acknowledgments
64 |
65 |
66 |
67 |
68 |
69 |
70 | ## About MountainVue
71 |
72 |
73 |
74 |
75 | MountainVue is a VS Code Extension that automatically scans your open workspace for Vue-based components and props to render component tree on extension initialization.
76 |
77 | Features:
78 | * Ability to parse through multi-layer Vue component structure as reusable data.
79 | * Parsing of Vue-based project directories to render a component tree in VS Code sidebar panel (via custom application icon).
80 | * Visualization of state and props utilized through Vuex (Vue’s Flux architecture; e.g. React-Redux).
81 | * Ability to export component tree as shareable visualizations (PDFs) for collaborative environments.
82 |
83 | MountainVue's goal is to extend reach to larger user base that specializes in Vue, bridging gap between communities among UI frameworks/libraries.
84 |
85 | (back to top )
86 |
87 |
88 |
89 | ### Built With
90 |
91 |
92 | * [Vue.js](https://vuejs.org/)
93 | * [Typescript](https://www.typescriptlang.org/)
94 | * [Javascript](https://www.javascript.com/)
95 | * [HTML](https://devdocs.io/html/)
96 | * [CSS](https://devdocs.io/css/)
97 |
98 |
99 | (back to top )
100 |
101 |
102 |
103 |
104 | ## Getting Started
105 |
106 | 1. After installing VS Code Extension, Click the MountainVue Icon on the sidebar tab.
107 |
108 |
109 | 2. Click upload button to select an entry point with a .vue file.
110 |
111 |
112 |
113 |
114 |
115 |
116 | 3. The sidebar will now display a component tree.
117 |
118 |
119 |
120 |
121 |
122 |
123 | (back to top )
124 |
125 |
126 |
127 |
128 |
135 |
136 |
137 |
138 |
139 | ## Roadmap
140 |
141 | - [x] Extension Sidebar listening for
142 | - [x] Complete Abstract Syntax Tree rendering logic for sidebar
143 | - [ ] Ability to parse through .vue Templates
144 | - [ ] Add logic to allow user to directly open a component file in the VS extension workspace from the AST
145 | - [ ] Multi-language Support
146 | - [ ] Chinese
147 |
148 |
149 | See the [open issues](https://github.com/oslabs-beta/MountainVue/issues) for a full list of proposed features (and known issues).
150 |
151 | (back to top )
152 |
153 |
154 |
155 |
156 | ## Contributing
157 |
158 | Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.
159 |
160 | If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement".
161 | Don't forget to give the project a star! Thanks again!
162 |
163 | 1. Fork the Project
164 | 2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
165 | 3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
166 | 4. Push to the Branch (`git push origin feature/AmazingFeature`)
167 | 5. Open a Pull Request
168 |
169 | (back to top )
170 |
171 |
172 |
173 |
179 |
180 |
181 |
182 |
183 | ## Creators
184 |
185 | Sean Lee - [@seanswlee](https://github.com/seanswlee)
186 |
187 | Matt Huang - [@matthewhuang24](https://github.com/matthewhuang24)
188 |
189 | Ryan Lim - [@ryanlim1](https://github.com/ryanlim1)
190 |
191 | Sohee Lee - [@sohee419](https://github.com/sohee419)
192 |
193 | Andy Tsou - [@andytsou19](https://github.com/andytsou19)
194 |
195 | Website: [MountainVue.app](https://mountainvue.app/)
196 |
197 | (back to top )
198 |
199 |
200 |
201 |
202 | ## Acknowledgments
203 |
204 |
205 | * [Parsing Strategy 1](https://observablehq.com/@ehouais/automatic-vue-js-single-file-components-hierarchy-graph-ge)
206 | * [Parsing Strategy 2](https://www.npmjs.com/package/vue-parser)
207 | * [Vue Component Tree Display](https://www.digitalocean.com/community/tutorials/vuejs-recursive-components)
208 | * [Vue Compiler](https://www.npmjs.com/package/vue-template-compiler)
209 | * [VS Code Extension](https://code.visualstudio.com/api)
210 |
211 |
212 |
213 | (back to top )
214 |
215 |
216 |
217 |
218 |
219 | [contributors-shield]: https://img.shields.io/github/contributors/oslabs-beta/MountainVue?style=for-the-badge
220 | [contributors-url]: https://github.com/oslabs-beta/MountainVue/graphs/contributors
221 | [forks-shield]: https://img.shields.io/github/forks/oslabs-beta/MountainVue?style=for-the-badge
222 | [forks-url]: https://github.com/oslabs-beta/MountainVue/network/members
223 | [stars-shield]: https://img.shields.io/github/stars/oslabs-beta/MountainVue?style=for-the-badge
224 | [stars-url]: https://github.com/oslabs-beta/MountainVue/stargazers
225 | [issues-shield]: https://img.shields.io/github/issues/oslabs-beta/MountainVue?style=for-the-badge
226 | [issues-url]: https://github.com/oslabs-beta/MountainVue/issues
227 |
229 | [linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=for-the-badge&logo=linkedin&colorB=555
230 | [linkedin-url]: https://www.linkedin.com/company/mountainvue/
231 |
232 |
--------------------------------------------------------------------------------
/json/demo.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "MountainVueApp",
3 | "children": [
4 | {
5 | "name": "Problems",
6 | "children": [
7 | {
8 | "name": "Problem1",
9 | "children": [
10 | {
11 | "name": "Lorem ipsum"
12 | }
13 | ]
14 | },
15 | {
16 | "name": "Problem2",
17 | "children": [
18 | {
19 | "name": "Lorem ipsum"
20 | }
21 | ]
22 | }
23 | ]
24 | },
25 | {
26 | "name": "Solutions",
27 | "children": [
28 | {
29 | "name": "Solution1",
30 | "children": [
31 | {
32 | "name": "Lorem ipsum"
33 | }
34 | ]
35 | },
36 | {
37 | "name": "Solution2",
38 | "children": [
39 | {
40 | "name": "Lorem ipsum"
41 | }
42 | ]
43 | }
44 | ]
45 | },
46 | {
47 | "name": "Challenges",
48 | "children": [
49 | {
50 | "name": "Challenge1",
51 | "children": [
52 | {
53 | "name": "Lorem ipsum"
54 | }
55 | ]
56 | },
57 | {
58 | "name": "Challenge2",
59 | "children": [
60 | {
61 | "name": "Lorem ipsum"
62 | }
63 | ]
64 | }
65 | ]
66 | },
67 | {
68 | "name": "ComingSoon",
69 | "children": [
70 | {
71 | "name": "Feature1",
72 | "children": [
73 | {
74 | "name": "Lorem ipsum"
75 | }
76 | ]
77 | },
78 | {
79 | "name": "Feature2",
80 | "children": [
81 | {
82 | "name": "Lorem ipsum"
83 | }
84 | ]
85 | },
86 | {
87 | "name": "Feature3",
88 | "children": [
89 | {
90 | "name": "Lorem ipsum"
91 | }
92 | ]
93 | }
94 | ]
95 | },
96 | {
97 | "name": "Team",
98 | "children": [
99 | {
100 | "name": "Ryan"
101 | },
102 | {
103 | "name": "Matt"
104 | },
105 | {
106 | "name": "Sohee"
107 | },
108 | {
109 | "name": "Sean"
110 | },
111 | {
112 | "name": "Andy"
113 | },
114 | {
115 | "name": "Uni"
116 | }
117 | ]
118 | }
119 | ]
120 | }
--------------------------------------------------------------------------------
/json/root.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "App.vue",
3 | "children": [
4 | {
5 | "name": "Home.vue",
6 | "children": [
7 | {
8 | "name": "Navbar.vue"
9 | },
10 | {
11 | "name": "Splash.vue"
12 | },
13 | {
14 | "name": "ComingSoon.vue"
15 | }
16 | ]
17 | },
18 | {
19 | "name": "About.vue",
20 | "children": [
21 | {
22 | "name": "Installation.vue",
23 | "children": [
24 | {
25 | "name": "Directions.vue"
26 | }
27 | ]
28 | },
29 | {
30 | "name": "Usage.vue"
31 | },
32 | {
33 | "name": "Contributions.vue"
34 | },
35 | {
36 | "name": "Acknowledgements.vue"
37 | }
38 | ]
39 | },
40 | {
41 | "name": "Team.vue",
42 | "children": [
43 | {
44 | "name": "Ryan.vue"
45 | },
46 | {
47 | "name": "Matt.vue"
48 | },
49 | {
50 | "name": "Sohee.vue"
51 | },
52 | {
53 | "name": "Sean.vue"
54 | },
55 | {
56 | "name": "Andy.vue"
57 | },
58 | {
59 | "name": "Uni.vue"
60 | }
61 | ]
62 | }
63 | ]
64 | }
--------------------------------------------------------------------------------
/media/gifs/Tree.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/MountainVue/29d3401d894ee20cff664c28f19c27348e49a4b3/media/gifs/Tree.gif
--------------------------------------------------------------------------------
/media/gifs/Upload.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/MountainVue/29d3401d894ee20cff664c28f19c27348e49a4b3/media/gifs/Upload.gif
--------------------------------------------------------------------------------
/media/mv-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/MountainVue/29d3401d894ee20cff664c28f19c27348e49a4b3/media/mv-logo.png
--------------------------------------------------------------------------------
/media/mv.svg:
--------------------------------------------------------------------------------
1 |
5 |
8 |
9 |
--------------------------------------------------------------------------------
/media/reset.css:
--------------------------------------------------------------------------------
1 | html {
2 | box-sizing: border-box;
3 | font-size: 13px;
4 | }
5 |
6 | *,
7 | *:before,
8 | *:after {
9 | box-sizing: inherit;
10 | }
11 |
12 | body,
13 | h1,
14 | h2,
15 | h3,
16 | h4,
17 | h5,
18 | h6,
19 | p,
20 | ol,
21 | ul {
22 | margin: 0;
23 | padding: 0;
24 | font-weight: normal;
25 | }
26 |
27 | img {
28 | max-width: 100%;
29 | height: auto;
30 | }
--------------------------------------------------------------------------------
/media/vscode.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --container-padding: 20px;
3 | --input-padding-vertical: 6px;
4 | --input-padding-horizontal: 4px;
5 | --input-margin-vertical: 4px;
6 | --input-margin-horizontal: 0;
7 | }
8 |
9 | body {
10 | padding: 0 var(--container-padding);
11 | color: var(--vscode-foreground);
12 | font-size: var(--vscode-font-size);
13 | font-weight: var(--vscode-font-weight);
14 | font-family: var(--vscode-font-family);
15 | background-color: var(--vscode-editor-background);
16 | }
17 |
18 | ol,
19 | ul {
20 | padding-left: var(--container-padding);
21 | }
22 |
23 | body > *,
24 | form > * {
25 | margin-block-start: var(--input-margin-vertical);
26 | margin-block-end: var(--input-margin-vertical);
27 | }
28 |
29 | *:focus {
30 | outline-color: var(--vscode-focusBorder) !important;
31 | }
32 |
33 | a {
34 | color: var(--vscode-textLink-foreground);
35 | }
36 |
37 | a:hover,
38 | a:active {
39 | color: var(--vscode-textLink-activeForeground);
40 | }
41 |
42 | code {
43 | font-size: var(--vscode-editor-font-size);
44 | font-family: var(--vscode-editor-font-family);
45 | }
46 |
47 | button {
48 | border: none;
49 | padding: var(--input-padding-vertical) var(--input-padding-horizontal);
50 | width: 100%;
51 | text-align: center;
52 | outline: 1px solid transparent;
53 | outline-offset: 2px !important;
54 | color: var(--vscode-button-foreground);
55 | background: var(--vscode-button-background);
56 | }
57 |
58 | button:hover {
59 | cursor: pointer;
60 | background: var(--vscode-button-hoverBackground);
61 | }
62 |
63 | button:focus {
64 | outline-color: var(--vscode-focusBorder);
65 | }
66 |
67 | button.secondary {
68 | color: var(--vscode-button-secondaryForeground);
69 | background: var(--vscode-button-secondaryBackground);
70 | }
71 |
72 | button.secondary:hover {
73 | background: var(--vscode-button-secondaryHoverBackground);
74 | }
75 |
76 | input:not([type='checkbox']),
77 | textarea {
78 | display: block;
79 | width: 100%;
80 | border: none;
81 | font-family: var(--vscode-font-family);
82 | padding: var(--input-padding-vertical) var(--input-padding-horizontal);
83 | color: var(--vscode-input-foreground);
84 | outline-color: var(--vscode-input-border);
85 | background-color: var(--vscode-input-background);
86 | }
87 |
88 | input::placeholder,
89 | textarea::placeholder {
90 | color: var(--vscode-input-placeholderForeground);
91 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mountainvue",
3 | "displayName": "MountainVue",
4 | "publisher": "MountainVue",
5 | "description": "TBA",
6 | "version": "0.0.1",
7 | "engines": {
8 | "vscode": "^1.62.0"
9 | },
10 | "categories": [
11 | "Visualization"
12 | ],
13 | "keywords": [
14 | "vue",
15 | "vs code extension",
16 | "component hierarchy",
17 | "devtools"
18 | ],
19 | "activationEvents": [
20 | "onStartupFinished"
21 | ],
22 | "main": "./dist/extension.js",
23 | "contributes": {
24 | "viewsContainers": {
25 | "activitybar": [
26 | {
27 | "id": "mv-sidebar-view",
28 | "title": "MountainVue",
29 | "icon": "media/mv.svg"
30 | }
31 | ]
32 | },
33 | "views": {
34 | "mv-sidebar-view": [
35 | {
36 | "type": "webview",
37 | "id": "mv-sidebar",
38 | "name": "MountainVue",
39 | "icon": "media/mv.svg",
40 | "contextualTitle": "MountainVue"
41 | }
42 | ]
43 | },
44 | "commands": []
45 | },
46 | "scripts": {
47 | "vscode:prepublish": "npm run package",
48 | "build": "concurrently \"cross-env NODE_ENV=development \" \"webpack\" \"npm-run-all -p build:*\"",
49 | "build:extension": "webpack --mode production",
50 | "build:sidebar": "webpack --config ./src/webviews/webpack.views.config.js",
51 | "watch": "webpack --watch",
52 | "package": "webpack --mode production --devtool hidden-source-map",
53 | "compile-tests": "tsc -p . --outDir out",
54 | "watch-tests": "tsc -p . -w --outDir out",
55 | "pretest": "npm run compile-tests && npm run compile && npm run lint",
56 | "lint": "eslint src --ext ts",
57 | "test": "node ./out/test/runTest.js"
58 | },
59 | "devDependencies": {
60 | "@babel/parser": "^7.16.2",
61 | "@babel/types": "^7.16.0",
62 | "@types/esprima": "^4.0.3",
63 | "@types/glob": "^7.1.4",
64 | "@types/mocha": "^9.0.0",
65 | "@types/node": "14.x",
66 | "@types/vscode": "^1.62.0",
67 | "@types/vue": "^2.0.0",
68 | "@typescript-eslint/eslint-plugin": "^5.1.0",
69 | "@typescript-eslint/parser": "^5.1.0",
70 | "@vscode/test-electron": "^1.6.2",
71 | "@vue/cli-plugin-babel": "^4.5.15",
72 | "@vue/cli-service": "^4.5.15",
73 | "@vue/compiler-sfc": "^3.2.22",
74 | "concurrently": "^6.3.0",
75 | "cross-env": "^7.0.3",
76 | "css-loader": "^6.5.1",
77 | "eslint": "^8.1.0",
78 | "esprima": "^4.0.1",
79 | "file-loader": "^6.2.0",
80 | "generate-source-map": "^0.0.5",
81 | "glob": "^7.1.7",
82 | "mini-css-extract-plugin": "^2.4.4",
83 | "mocha": "^9.1.3",
84 | "node-sass": "^6.0.1",
85 | "npm-run-all": "^4.1.5",
86 | "postcss-import": "^14.0.2",
87 | "sass": "^1.43.4",
88 | "sass-loader": "^12.3.0",
89 | "style-loader": "^3.3.1",
90 | "ts-loader": "^9.2.6",
91 | "typescript": "^4.4.4",
92 | "vscode-test": "^1.6.1",
93 | "vue": "^3.2.22",
94 | "vue-loader": "^16.8.3",
95 | "vue-loader-plugin": "^1.3.0",
96 | "vue-style-loader": "^4.1.3",
97 | "vue-template-compiler": "^2.6.14",
98 | "webpack": "^5.52.1",
99 | "webpack-cli": "^4.8.0"
100 | },
101 | "dependencies": {
102 | "core-js": "^3.19.1",
103 | "fs": "^0.0.1-security",
104 | "path": "^0.12.7",
105 | "register-service-worker": "^1.7.2"
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/MVParser.ts:
--------------------------------------------------------------------------------
1 | // import * as babelParser from '@babel/parser';
2 | // import * as path from 'path';
3 | // import * as fs from 'fs';
4 | // import { getNonce } from "./getNonce";
5 | // import { File } from '@babel/types';
6 | // import Tree from './types/Tree';
7 | // import Imports from './types/Imports';
8 |
9 | // class MVParser {
10 | // filePath: string;
11 | // tree: Tree | undefined;
12 |
13 | // constructor(path: string) {
14 | // this.filePath = path;
15 | // this.tree = undefined;
16 | // }
17 |
18 | // public parse(): Tree | undefined {
19 | // const root = {
20 | // id: getNonce(),
21 | // name: path.basename(this.filePath).replace(/\.(vue)$/, ''),
22 | // fileName: path.basename(this.filePath),
23 | // path: this.filePath,
24 | // importPath: '/',
25 | // expanded: false,
26 | // depth: 0,
27 | // count: 1,
28 | // thirdParty: false,
29 | // vueRouter: false,
30 | // vuexStore: false,
31 | // children: [],
32 | // parent: [],
33 | // props: {},
34 | // error: ''
35 | // };
36 |
37 | // this.tree = root;
38 | // this.parser(root);
39 |
40 | // return this.tree;
41 | // }
42 |
43 | // public getTree(): Tree | undefined {
44 | // return this.tree;
45 | // }
46 |
47 | // public setTree(tree: Tree): void {
48 | // this.filePath = tree.path;
49 | // this.tree = tree;
50 | // }
51 |
52 | // public updateTree(path: string): Tree | undefined {
53 | // let children: any[] = [];
54 |
55 | // const getChildren = (node: Tree): void => {
56 | // const { depth, path, expanded } = node;
57 | // children.push({ depth, path, expanded });
58 | // };
59 |
60 | // const balanceDepth = (node: Tree): void => {
61 | // children.forEach(child => {
62 | // if (child.depth === node.depth && child.path === node.path && child.expanded) {
63 | // node.expanded = true;
64 | // }
65 | // });
66 | // };
67 |
68 | // const updateChildren = (node: Tree): void => {
69 | // if (node.path === path) {
70 | // node.children.forEach(child => {
71 | // this.traverseTree(getChildren, child);
72 | // });
73 |
74 | // const newNode = this.parser(node);
75 |
76 | // this.traverseTree(balanceDepth, newNode);
77 |
78 | // children = [];
79 | // }
80 | // };
81 |
82 | // this.traverseTree(updateChildren, this.tree);
83 |
84 | // return this.tree;
85 | // }
86 |
87 | // public toggleExpanded(id: string, expanded: boolean): Tree | undefined {
88 | // const updateExpanded = (node: Tree): void => {
89 | // if (node.id === id) {
90 | // node.expanded = expanded;
91 | // }
92 | // };
93 |
94 | // this.traverseTree(updateExpanded, this.tree);
95 |
96 | // return this.tree;
97 | // }
98 |
99 | // private traverseTree(callback: Function, node: Tree | undefined = this.tree): any {
100 | // if (!node) {
101 | // return;
102 | // }
103 |
104 | // callback(node);
105 |
106 | // node.children.forEach(child => {
107 | // this.traverseTree(callback, child);
108 | // });
109 | // }
110 |
111 | // private parser(tree: Tree): Tree | undefined {
112 | // if (!['\\', '/', '.'].includes(tree.importPath[0])) {
113 | // tree.thirdParty = true;
114 |
115 | // if (tree.fileName === 'vue-router') {
116 | // tree.vueRouter = true;
117 | // }
118 |
119 | // return;
120 | // }
121 |
122 | // const fileName = this.getFileName(tree);
123 |
124 | // if (!fileName) {
125 | // tree.error = 'File does not exist';
126 | // return;
127 | // }
128 |
129 | // if (tree.parent.includes(tree.path)) {
130 | // return;
131 | // }
132 |
133 | // let ast: babelParser.ParseResult;
134 |
135 | // try {
136 | // ast = babelParser.parse(fs.readFileSync(path.resolve(tree.path), 'utf-8'), {
137 | // sourceType: 'module',
138 | // tokens: true,
139 | // plugins: ['typescript']
140 | // });
141 | // } catch (err) {
142 | // tree.error = 'Could not parse uploaded file';
143 | // return tree;
144 | // }
145 |
146 | // const imports = this.getImports(ast.program.body);
147 |
148 | // // tree.children = this.getVueChildren(ast.tokens, imports, tree);
149 | // // tree.vuexStore = this.checkForVuex(ast.tokens, imports);
150 | // // tree.children.forEach(child => this.parser(child));
151 |
152 | // return tree;
153 | // }
154 |
155 | // private getFileName(tree: Tree): string | undefined {
156 | // const fileExt = path.extname(tree.path);
157 | // let fileName: string | undefined = tree.fileName;
158 |
159 | // if (!fileExt) {
160 | // const fileDir = fs.readdirSync(path.dirname(tree.path));
161 | // const regEx = new RegExp(`${tree.fileName}.(vue)$`);
162 | // fileName = fileDir.find(path => path.match(regEx));
163 | // fileName ? tree.path += path.extname(fileName) : null;
164 | // }
165 |
166 | // return fileName;
167 | // }
168 |
169 | // private getImports(body: { [key: string]: any }[]): Imports {
170 | // const bodyImports = body.filter(item => item.type === 'ImportDeclaration' || 'VariableDeclaration');
171 |
172 | // const reduceImports = bodyImports.reduce((output, currVal) => {
173 | // if (currVal.type === 'ImportDeclaration') {
174 | // currVal.specifiers.forEach((val: any) => {
175 | // output[val.local.name] = {
176 | // importPath: currVal.source.value,
177 | // importName: val.imported ? val.imported.name : val.local.name
178 | // };
179 | // });
180 | // }
181 |
182 | // if (currVal.type === 'VariableDeclaration') {
183 | // const importPath = this.findVarDecImports(currVal.declartions[0]);
184 |
185 | // if (importPath) {
186 | // const importName = currVal.declarations[0].id.name;
187 | // output[currVal.declarations[0].id.name] = {
188 | // importPath,
189 | // importName
190 | // };
191 | // }
192 | // }
193 |
194 | // return output;
195 | // }, {});
196 |
197 | // return reduceImports;
198 | // }
199 |
200 | // private findVarDecImports(ast: { [key: string]: any }): any {
201 | // if (ast.hasOwnProperty('callee') && ast.callee.type === 'Import') {
202 | // return ast.arguments[0].value;
203 | // }
204 |
205 | // for (let key in ast) {
206 | // if (ast.hasOwnProperty(key) && typeof ast[key] === 'object' && ast[key]) {
207 | // const importPath = this.findVarDecImports(ast[key]);
208 | // if (importPath) {
209 | // return importPath;
210 | // }
211 | // }
212 | // }
213 |
214 | // return false;
215 | // }
216 |
217 | // // private getVueChildren(tokens: any[], importData: Imports, parentNode: Tree): Tree | undefined {
218 | // // let childNodes: { [key: string]: Tree } = {};
219 | // // let props: { [key: string]: boolean } = {};
220 | // // let token: { [key: string]: any };
221 |
222 | // // tokens.forEach((token, i) => {
223 | // // if (token.type.label === )
224 | // // })
225 | // // }
226 | // }
227 |
228 | // export default MVParser;
229 |
--------------------------------------------------------------------------------
/src/SidebarProvider.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from 'vscode';
2 | import getNonce from './getNonce';
3 | // import MVParser from './MVParser';
4 | import Tree from './types/Tree';
5 | export class SidebarProvider implements vscode.WebviewViewProvider {
6 | _view?: vscode.WebviewView;
7 | // parser: MVParser | undefined;
8 | // private readonly context: vscode.ExtensionContext;
9 |
10 | constructor(private readonly _extensionUri: vscode.Uri) {
11 | // this.context = context;
12 | // this._extensionUri = context.extensionUri;
13 |
14 | // const state: Tree | undefined = context.workspaceState.get('mountainvue');
15 |
16 | // Parsing logic in progress
17 | // if (state) {
18 | // this.parser = new MVParser(state.filePath);
19 | // }
20 | }
21 |
22 | public resolveWebviewView(webviewView: vscode.WebviewView) {
23 | this._view = webviewView;
24 |
25 | webviewView.webview.options = {
26 | // Allow scripts in the webview
27 | enableScripts: true,
28 |
29 | localResourceRoots: [
30 | this._extensionUri
31 | ],
32 | };
33 |
34 | webviewView.webview.html = this._getHtmlForWebview(webviewView.webview);
35 |
36 | // Extension reducer in progress
37 | // webviewView.webview.onDidReceiveMessage(async (data) => {
38 | // switch (data.type) {
39 | // case 'onFile': {
40 | // if (!data.type) {
41 | // return;
42 | // }
43 |
44 | // this.parser = new MVParser(data.value);
45 | // this.parser.parse();
46 | // // this.updateView();
47 | // break;
48 | // }
49 | // }
50 | // });
51 | }
52 |
53 | public revive(panel: vscode.WebviewView) {
54 | this._view = panel;
55 | }
56 |
57 | private _getHtmlForWebview(webview: vscode.Webview) {
58 | const styleResetUri = webview.asWebviewUri(
59 | vscode.Uri.joinPath(
60 | this._extensionUri, 'media', 'reset.css')
61 | );
62 |
63 | const styleVSCodeUri = webview.asWebviewUri(
64 | vscode.Uri.joinPath(
65 | this._extensionUri, 'media', 'vscode.css')
66 | );
67 |
68 | // const styleMainUri = webview.asWebviewUri(
69 | // vscode.Uri.joinPath(
70 | // this._extensionUri, 'dist', 'style.css')
71 | // );
72 |
73 | const scriptUri = webview.asWebviewUri(
74 | vscode.Uri.joinPath(
75 | this._extensionUri, 'dist', 'app.js')
76 | );
77 |
78 | const nonce = getNonce();
79 |
80 | return `
81 |
82 |
83 |
84 |
85 |
91 |
92 |
93 |
94 |
95 | MV
96 |
99 |
100 |
101 |
102 |
82 |
83 |
125 |
--------------------------------------------------------------------------------
/src/webviews/components/MVTree.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
13 | {{ expanded ? '⋎' : '≻' }}
14 |
15 |
20 | {{ node.name }}
21 |
22 |
23 |
24 |
25 | $emit('onClick', node)"
31 | />
32 |
33 |
34 |
35 |
36 |
68 |
69 |
--------------------------------------------------------------------------------
/src/webviews/components/Tree.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
21 |
22 |
--------------------------------------------------------------------------------
/src/webviews/globals.d.ts:
--------------------------------------------------------------------------------
1 | import * as _vscode from 'vscode';
2 |
3 | declare global {
4 | const tsvscode: {
5 | postMessage: ({ type: string, value: any }) => void;
6 | };
7 | }
8 |
9 | export default tsvscode;
--------------------------------------------------------------------------------
/src/webviews/img/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/MountainVue/29d3401d894ee20cff664c28f19c27348e49a4b3/src/webviews/img/logo.png
--------------------------------------------------------------------------------
/src/webviews/pages/App.js:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue';
2 | import App from '../components/App.vue';
3 |
4 | createApp(App).mount('#app');
5 |
--------------------------------------------------------------------------------
/src/webviews/tsconfig.views.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "outDir": "../../dist",
4 | "lib": [
5 | "dom"
6 | ],
7 | "module": "es6",
8 | "target": "es5",
9 | "jsx": "react",
10 | "allowJs": true,
11 | "moduleResolution": "node",
12 | "sourceMap": true,
13 | }
14 | }
--------------------------------------------------------------------------------
/src/webviews/webpack.views.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const { VueLoaderPlugin } = require('vue-loader');
3 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
4 |
5 | module.exports = {
6 | entry: path.resolve(__dirname, './pages/App.js'),
7 | mode: 'production',
8 | module: {
9 | rules: [
10 | {
11 | test: /\.ts?$/,
12 | use: {
13 | loader: 'ts-loader',
14 | options: {
15 | configFile: 'tsconfig.views.json',
16 | appendTsSuffixTo: [/\.vue$/],
17 | },
18 | },
19 | exclude: /node_modules/,
20 | },
21 | {
22 | test: /\.vue$/,
23 | loader: 'vue-loader',
24 | },
25 | {
26 | test: /\.vue\.(s?[ac]ss)$/,
27 | use: ['vue-style-loader', 'css-loader', 'sass-loader'],
28 | },
29 | {
30 | test: /(? https://webpack.js.org/configuration/node/
13 | mode: 'none', // this leaves the source code as close as possible to the original (when packaging we set this to 'production')
14 |
15 | entry: './src/extension.ts', // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/
16 | output: {
17 | // the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/
18 | path: path.resolve(__dirname, 'dist'),
19 | filename: 'extension.js',
20 | libraryTarget: 'commonjs2'
21 | },
22 | externals: {
23 | vscode: 'commonjs vscode' // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/
24 | // modules added here also need to be added in the .vscodeignore file
25 | },
26 | resolve: {
27 | // support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader
28 | extensions: ['.ts', '.js']
29 | },
30 | module: {
31 | rules: [
32 | {
33 | test: /\.ts$/,
34 | exclude: /node_modules/,
35 | use: [
36 | {
37 | loader: 'ts-loader'
38 | }
39 | ]
40 | }
41 | ]
42 | },
43 | devtool: 'nosources-source-map',
44 | infrastructureLogging: {
45 | level: "log", // enables logging required for problem matchers
46 | },
47 | };
48 | module.exports = [ extensionConfig ];
--------------------------------------------------------------------------------