diff --git a/.eslintrc.json b/.eslintrc.json index ffb9ed2..06c441b 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,14 +1,24 @@ { "extends": ["eslint-config-node-roboleary"], - "env": { - "mocha": true - }, - "settings": { - "import/core-modules": [ "vscode" ] - }, - "rules": { - "node/no-missing-require": ["error", { - "allowModules": [ "vscode"] - }] - } + "env": { + "mocha": true, + "es2020": true + }, + "settings": { + "import/core-modules": ["vscode"] + }, + "rules": { + "node/no-missing-require": [ + "error", + { + "allowModules": ["vscode"] + } + ], + "node/no-unpublished-require": [ + "error", + { + "allowModules": ["mocha"] + } + ] + } } diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 0e6f1bd..072e73c 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -25,11 +25,11 @@ A clear and concise description of what you expected to happen. If applicable, add screenshots to help explain your problem. -## Environment information +## Platform information Please complete the following information: - On the main menu, go to *Help*, and select *About* from the drop down. Copy the information from the *About* dialog. -- Are you are working remotely or using WSL? Please state this too. +- Are you are working remotely or using WSL? ## Additional context diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..2a8d581 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,24 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +## Is your feature request related to a problem? + +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +## Describe the solution you'd like + +A clear and concise description of what you want to happen. + +## Describe alternatives you've considered + +A clear and concise description of any alternative solutions or features you've considered. + +## Additional context + +Add any other context or screenshots about the feature request here. diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 816a803..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "markyMarkdown.tableOfContents.updateOnSave": true, - "markyMarkdown.tableOfContents.label": "**Table of Contents**", - "svg.preview.background": "transparent" -} diff --git a/.vscodeignore b/.vscodeignore index d0be3a7..aaf9a2c 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -8,6 +8,7 @@ test **/*.map **/.eslintrc.json src +refactor !script/main.js webpack.config.js img/** diff --git a/CHANGELOG.md b/CHANGELOG.md index b4b1da8..afa14c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,37 @@ All notable changes to this project are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.0.0] + +### Changed + +- Major refactor of codebase!! +- Tweaked the appearance of *view* in following ways: + - Updated the *table of contents* to show an entry for the snippets file in an extension. + - Show *all* snippet files. Previously if a file was empty, it was not shown. + - For extensions section, make the file section with the heading (snippet file name) and languages a sticky section. + - Moved the "view source" button to be on same line as heading and to be be part of a sticky section. + - For the table of snippets: + - Show `prefix` as an unstyled list. If it has multiple items, show as a comman-separated list + with each item on a separate line. + - Format the `scope` content to be a sorted list and have a space between each item. + - Tweaked colours, spacing, and various styles to improve readability. + - Change the `h3` headings in the project, user, and "VS Code" sections. Now, it shows the filename with the extension. Previously, the extension was excluded for brevity. Since a snippet file can be a `.json` or `.code-snippets` file, it is better to be give the complete filename. + - Changed the title for "app" snippets section from "VS Code Snippets" to "App Snippets". +- Change `prefix` to accept string or array in *snippet.js*. +- Change `scope` to be a formatted string (sort items and normalize space between items) in *snippet.js*. +- Change the title of the `snippets-ranger.add` command from "Snippets Ranger: Add New Snippet" to "Add new snippet to snippets file...". +- Change the `snippets-ranger.add` command to transform a multi-line string into multiple elements in the array. +- Updated README copy and added new screenshots. + +### Removed + +- Removed the "back to button" that resided in the top-right corner of *view*. + +### Fixed + +- For the `snippets-ranger.add` command, it escapes dollar signs in the selected code. This ensures that they are not interpeted as tabstops. + ## [0.25.0, 0.25.1] - 2023-10-16 ### Changed diff --git a/README.md b/README.md index f9bca71..5c7f4b2 100644 --- a/README.md +++ b/README.md @@ -10,68 +10,80 @@

View and edit all your snippets in one purty place. Yee-haw!

-Made for VSCode -Visual Studio Marketplace Version -Made for VSCode +Visual Studio Marketplace Version +Extension file size in bytes -Visual Studio Marketplace Rating -downloads -installs -Built with sarsaparilla and javascript -Buy me a coffee +Visual Studio Marketplace Rating +downloads +installs +Built with sarsaparilla and javascript +Buy me a coffee

-

-recording of  exploring view opened from the command 'Snippets Ranger: Show me that dur Range, Partner'. An entry of 'Markdown snippets' from the table of contents is selected and clicked, it takes the user down to the table with the snippets displayed for that extension. -

+![Screenshot of the view. It shows the user snippets for the markdown language in a table with the columns: prefix, name, description, body and action.](img/screenshots/view-showcase.jpg) -**Snippets are grouped as: *Project*, *User*, *Extension*, and *VS Code*.** +Snippets are shown in an **easy to read [webview](https://code.visualstudio.com/api/extension-guides/webview)**. -The table of contents facilitates quick navigation to a snippets set. Pressing the Home key will return you to the table of contents. +Snippets are formed into posses: +- ***Project***: These are the snippets contained in the `.vscode` folder of the current workspace, +- ***User***: These are the global snippet files (`.code-snippets` files) and language snippet files (`.json` files) that you created as an user on your system, +- ***Extension***: These are the snippets files that are included in extensions you have installed, +- ***App***: These are the snippets files that are packaged with VS Code. -There are sticky headings to ensure you can browse through long snippet lists without losing context. 🦎🔝 +The extension uses the exact same source files as VS Code does. No double-crossing rattlesnakes! 🐍 -You can go to the source snippet file directly with the *View Source File* button. The extension uses **the exact same source files as VS Code does**. +## Easy navigation -![view source screenshot](img/screenshots/view-source.png) +There are **sticky headings** to ensure you can browse through long snippet lists without losing context. 🦎🔝 -**Editing is a piece of cake**.🍰 +![Demonstration of scrolling through the user snippets section. There are 3 sticky sections: the h2 heading (user snippets), a section with a, h3 heading (markdown.json) and view source button, and the table header.W](img/screenshots/sticky-headers.webp) -![view source screenshot](img/screenshots/edit.png) +The **table of contents** facilitates quick navigation to a snippets set. -The *Edit* action button will take you to the specific snippet in the source file to perform an edit. The *Delete* action button will delete the snippet straight away. +![Screenshot of the table of contents for the view.](img/screenshots/toc.webp) -## Activation +Pressing the Home key will return you to the table of contents. -The extension is only loaded when one of the commands are executed. +## Easy editing + +You can **open the snippets file with the *View Source File* button** contained in the sticky header for each snippets file listed in the view. + +In the table, you can **edit individual snippet with the buttons in each row**: +- The *Edit* action button (identified by the pen icon) will take you to the specific snippet in the source file to perform an edit. +- The *Delete* action button (identified by the trash icon) will delete the snippet straight away without opening the file. + +![view source screenshot](img/screenshots/action-highlight.webp) + +If you are working in code and would like to **quickly add a snippet to a snippets file, you can use the `Snippets Ranger: Add new snippet to snippets file...` command**. It has 3 easy steps: +1. Select some code (no selection is fine too) and run the command, +1. Choose an existing snippets file or create a new file from the menu, +1. The file will be opened with a new snippet. Your selection will be in the `body` field as an array of values. You can tab through the properties to fill each one out. + +![using add command](img/screenshots/add-command.png) ## Commands -The following commands can be run from the Command Palette (`Ctrl+Shift+P`): +The following commands are available: -1. **`Snippets Ranger: Show me that dur Range, Partner`**: Opens the view that lists all snippets. -1. **`Snippets Ranger: Add New Snippet`**: Quickly add a new snippet to a snippet file of your choosing. +1. **`Snippets Ranger: Show me that dur Range, Partner`**: Opens the view that lists all your snippets. +1. **`Snippets Ranger: Add new snippet to snippets file...`**: Quickly add a new snippet to a snippet file of your choosing. If you have code selected, this selection will be added to the `body` of the snippet. Any dollar signs in the selection will be escaped (preceded by 2 backslashes) to prevent them being interpeted as tab stops. -![add new snippet](img/screenshots/add-new.webp) +## Activation + +The extension is only loaded when one of the commands are executed. ## Performance -To gather and render approx 6000 snippets sourced from 18 different files, it takes 4.5 seconds on a modestly-specced 4-year old laptop running Ubuntu 18. 🚀 +To gather and render approx 6000 snippets sourced from 18 different files, it takes 4.5 seconds on a modestly-specced laptop running Ubuntu 18. 🚀 ## Contribute -Contributions are welcome. If you have a suggestion or find a bug, please file an issue. - -Please do not offer a PR without raising an issue first, my time for reviews are limited. You can [support me](https://ko-fi.com/roboleary) to increase my time available. - -## Appreciate +Contributions are welcome. If you have a suggestion or find a bug, please file an issue. Please do not offer a PR without raising an issue first, my time for reviews are limited. -You can show your appreciation by: -1. [Buying me a coffee or sponsoring me](https://ko-fi.com/roboleary) -1. Leaving a positive review in the [visual studio marketplace](https://marketplace.visualstudio.com/items?itemName=robole.snippets-ranger&ssr=false#review-details). -1. Starring the repo 🌟. +To help other people find the extension, you can [star the repo 🌟](https://github.com/robole/vscode-snippets-ranger), and leave a positive review in the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=robole.snippets-ranger&ssr=false#review-details) or [Open VSX Registry](https://open-vsx.org/extension/robole/snippets-ranger/reviews). -This will **help other people find the extension**. It will **encourage me to continue maintenance**, and may provide **a path to dedicating more time to open-source** in the future. +You can [support me](https://ko-fi.com/roboleary) to make issues in this project a higher priority and allow me to dedicate more time I can dedicate to open-source projects. ## Learn more about snippets diff --git a/img/screenshots/action-highlight.png b/img/screenshots/action-highlight.png new file mode 100644 index 0000000..320dad5 Binary files /dev/null and b/img/screenshots/action-highlight.png differ diff --git a/img/screenshots/action-highlight.webp b/img/screenshots/action-highlight.webp new file mode 100644 index 0000000..a2cdaef Binary files /dev/null and b/img/screenshots/action-highlight.webp differ diff --git a/img/screenshots/add-command.png b/img/screenshots/add-command.png new file mode 100644 index 0000000..2cb302c Binary files /dev/null and b/img/screenshots/add-command.png differ diff --git a/img/screenshots/add-new.jpg b/img/screenshots/add-new.jpg deleted file mode 100644 index 8b9dd9a..0000000 Binary files a/img/screenshots/add-new.jpg and /dev/null differ diff --git a/img/screenshots/add-new.webp b/img/screenshots/add-new.webp deleted file mode 100644 index c64308a..0000000 Binary files a/img/screenshots/add-new.webp and /dev/null differ diff --git a/img/screenshots/add-new.xcf b/img/screenshots/add-new.xcf deleted file mode 100644 index c1aacbb..0000000 Binary files a/img/screenshots/add-new.xcf and /dev/null differ diff --git a/img/screenshots/demo.mp4 b/img/screenshots/demo.mp4 deleted file mode 100644 index 747d75f..0000000 Binary files a/img/screenshots/demo.mp4 and /dev/null differ diff --git a/img/screenshots/demo.webp b/img/screenshots/demo.webp deleted file mode 100644 index 4d2b020..0000000 Binary files a/img/screenshots/demo.webp and /dev/null differ diff --git a/img/screenshots/edit.png b/img/screenshots/edit.png deleted file mode 100644 index e27a37d..0000000 Binary files a/img/screenshots/edit.png and /dev/null differ diff --git a/img/screenshots/sticky-headers.mp4 b/img/screenshots/sticky-headers.mp4 new file mode 100644 index 0000000..679ab73 Binary files /dev/null and b/img/screenshots/sticky-headers.mp4 differ diff --git a/img/screenshots/sticky-headers.webp b/img/screenshots/sticky-headers.webp new file mode 100644 index 0000000..1c59be6 Binary files /dev/null and b/img/screenshots/sticky-headers.webp differ diff --git a/img/screenshots/table.png b/img/screenshots/table.png new file mode 100644 index 0000000..074d2d3 Binary files /dev/null and b/img/screenshots/table.png differ diff --git a/img/screenshots/toc.png b/img/screenshots/toc.png new file mode 100644 index 0000000..4bac2a3 Binary files /dev/null and b/img/screenshots/toc.png differ diff --git a/img/screenshots/toc.webp b/img/screenshots/toc.webp new file mode 100644 index 0000000..42508f3 Binary files /dev/null and b/img/screenshots/toc.webp differ diff --git a/img/screenshots/view-showcase.jpg b/img/screenshots/view-showcase.jpg new file mode 100644 index 0000000..3866854 Binary files /dev/null and b/img/screenshots/view-showcase.jpg differ diff --git a/img/screenshots/view-showcase.webp b/img/screenshots/view-showcase.webp new file mode 100644 index 0000000..c5ffa14 Binary files /dev/null and b/img/screenshots/view-showcase.webp differ diff --git a/img/screenshots/view-source.png b/img/screenshots/view-source.png deleted file mode 100644 index 52a6a29..0000000 Binary files a/img/screenshots/view-source.png and /dev/null differ diff --git a/jsconfig.json b/jsconfig.json index 6edc71d..f2e61a4 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "module": "commonjs", "target": "es6", - "checkJs": true /* Typecheck .js files. */, + "checkJs": false /* Typecheck .js files. */, "lib": ["es6"] }, "exclude": ["node_modules", "dist"] diff --git a/package.json b/package.json index 448657d..282e845 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ }, "description": "View and edit all your snippets in one purty place. Yee-haw!", "icon": "img/logo.png", - "version": "0.25.1", + "version": "1.0.0", "engines": { "vscode": "^1.4.0", "node": ">=12.0.0" @@ -90,7 +90,7 @@ "onCommand:snippets-ranger.show", "onCommand:snippets-ranger.add" ], - "main": "./dist/extension.js", + "main": "./dist/main.js", "contributes": { "commands": [ { @@ -100,7 +100,7 @@ }, { "command": "snippets-ranger.add", - "title": "Add New Snippet", + "title": "Add new snippet to snippets file...", "category": "Snippets Ranger" } ] diff --git a/script/main.js b/script/main.js index aa0f93b..1a06153 100644 --- a/script/main.js +++ b/script/main.js @@ -3,31 +3,6 @@ let script = (function () { const vscode = acquireVsCodeApi(); - let toTopLink = document.getElementById("toTopLink"); - let debounceTimer; - - window.onscroll = function () { - if (debounceTimer) { - window.clearTimeout(debounceTimer); - } - debounceTimer = window.setTimeout(() => { - showToTopLink(); - }, 100); - }; - - function showToTopLink() { - let gap = 750; - - if ( - document.body.scrollTop > gap || - document.documentElement.scrollTop > gap - ) { - toTopLink.style.display = "block"; - } else { - toTopLink.style.display = "none"; - } - } - let openFile = function (path) { vscode.postMessage({ command: "openSnippetFile", @@ -43,7 +18,7 @@ let script = (function () { }); }; - let deleteSnippet = function (path, snippetName, rowIndex) { + let deleteSnippet = function (path, snippetName) { vscode.postMessage({ command: "deleteSnippet", path, @@ -52,7 +27,7 @@ let script = (function () { let decodedPath = decodeURIComponent(path); let row = document.querySelector( - `table[data-path='${decodedPath}'] tbody tr:nth-child(${rowIndex})` + `table[data-path='${decodedPath}'] tbody tr[data-name='${snippetName}']` ); if (row !== null) { diff --git a/src/actions/add.js b/src/actions/add.js new file mode 100644 index 0000000..b005dec --- /dev/null +++ b/src/actions/add.js @@ -0,0 +1,129 @@ +/* eslint-disable no-useless-escape */ +/* eslint-disable no-template-curly-in-string */ +const vscode = require("vscode"); +const util = require("../helper/util"); +const { convertToArray } = require("../helper/format"); + +/** + * @async + * Add a new snippet to a snippet file of the user's choosing. The user is presented with a + * QuickPick menu to choose an existing snippet file or to create a new file. It will open the file + * and insert a snippet to enable you to complete a snippet entry in the file. The `body` field will + * be populated with selected from the active `TextEditor`. + */ +async function addSnippet() { + let activeEditor = vscode.window.activeTextEditor; + let selection = ""; + + if (activeEditor) { + selection = activeEditor.document.getText(activeEditor.selection); + } + + // If a file is selected from QuickPick, `true` is returned. If 'New Global Snippets file..' is selected + // or no file is selected, then `undefined` is returned + let selectedFile = await vscode.commands.executeCommand( + "workbench.action.openSnippets" + ); + activeEditor = vscode.window.activeTextEditor; + + // User did not select an option. This is not exact!! Exception is when a user does not select a file + // and has a .code-snippets file open, this will insert a snippet into that file. + if ( + selectedFile === undefined && + activeEditor.document.fileName.endsWith(".code-snippets") === false + ) { + return; + } + + let snippetString = createSnippetString(selection); + await insertSnippetAtTop(snippetString); +} + +/** + * Insert a snippet to the first line, second character of the active text editor + * + * @param {string} text - The text to convert + * @returns {vscode.SnippetString} + */ +async function insertSnippetAtTop(snippetString) { + let activeEditor = vscode.window.activeTextEditor; + + if (activeEditor === undefined) { + return; + } + + let range = new vscode.Range(0, 1, 0, 1); + + await activeEditor.insertSnippet(snippetString, range); +} + +/** + * Create a SnippetString object with tab stops for easy filling of fields. The `body` field is populated from + * the `bodyText` argument, the value is converted into an array and has some special characters + * such as the dollar sign escaped. + * + * @param {string} text - The text to convert + * @returns {vscode.SnippetString} + */ +function createSnippetString(bodyText = "") { + let body; + let eol = util.getEndOfLineDelimiter(); + + if (bodyText.length === 0) { + body = `["\$5"]`; + } else { + let escapedText = escapeDollarSigns(bodyText); + body = printAsArray(escapedText); + } + + let string = `${eol}\t"\${1:name}" : {${eol}`; + string += `\t\t"prefix" : "\$2",${eol}\t\t"description": "\$4",`; + string += `${eol}\t\t"body" : ${body}${eol}\t},\$0`; + + return new vscode.SnippetString(string); +} + +/** + * Convert a string into an array and print. The text is split into element using a line break as a delimiter. + * It is printed in the form of: ["element1", "element2"] + * @param {string} text - The text to convert + * @returns {string} + */ +function printAsArray(text) { + let array = convertToArray(text); + let string = "["; + + array.forEach((element, index) => { + string += `"${escapeDoubleQuotes(element)}"`; + + if (index !== array.length - 1) { + string += ", "; + } + }); + + string += "]"; + + return string; +} + +/** + * Escape dollar signs with multiple backslashes. This is to have a string retain a dollar sign + * when it is used as text inserted into a snippet file and then used as a snippet. This requires + * an unusual amount of backslash escapes to make it through the 2 steps! + * @param {string} text - the text to update + * @returns {string} + */ +function escapeDollarSigns(text) { + return text.replaceAll(/\$/gm, "\\\\\\\\\\$"); +} + +/** + * Escape double quote characters. Two backslashes are required in strings. + * @param {string} text - the text to update + * @returns {string} + */ +function escapeDoubleQuotes(text) { + return text.replaceAll(/"/gm, `\\"`); +} + +module.exports = { addSnippet }; diff --git a/src/actions/delete.js b/src/actions/delete.js new file mode 100644 index 0000000..656aa99 --- /dev/null +++ b/src/actions/delete.js @@ -0,0 +1,17 @@ +const fs = require("fs"); +const { parse } = require("../core/parser"); + +/** + * @async + * Delete a snippet from a snippet file. + * @param {vscode.Uri} uri URI of the snippet file you want to delete the snippet from. + * @param {String} snippetName The name of the snipepet to delete + * @returns {Promise} The TextEditor that contains the user snippets document. + */ +async function deleteSnippet(uri, snippetName) { + let json = await parse(uri.fsPath); + delete json[snippetName]; + await fs.promises.writeFile(uri.fsPath, JSON.stringify(json, null, 2)); +} + +module.exports = { deleteSnippet }; diff --git a/src/actions/edit.js b/src/actions/edit.js new file mode 100644 index 0000000..7279c37 --- /dev/null +++ b/src/actions/edit.js @@ -0,0 +1,32 @@ +const vscode = require("vscode"); +const util = require("../helper/util"); + +/** + * @async + * Open a snippet file and jump to the snippet. If the snippet is not + * found, it will open the snippet file with the cursor on the first line. + * @returns {Promise} The `TextEditor` that contains the user snippets document. + */ + +async function editSnippet(uri, snippetName) { + let textEditor = await vscode.window.showTextDocument(uri); + let doc = textEditor.document; + let text = doc.getText(); + + let escapedSnippetName = util.escapeStringRegexp(snippetName); + let regex = new RegExp(`"${escapedSnippetName}".*?:.*?\\{`); + let match = regex.exec(text); + let index = 0; + + if (match !== null) { + index = match.index + 1; + } + + let position = textEditor.document.positionAt(index); + let range = new vscode.Range(position, position); + textEditor.revealRange(range, vscode.TextEditorRevealType.AtTop); + textEditor.selection = new vscode.Selection(position, position); + return textEditor; +} + +module.exports = { editSnippet }; diff --git a/src/core/env.js b/src/core/env.js new file mode 100644 index 0000000..b5f3d73 --- /dev/null +++ b/src/core/env.js @@ -0,0 +1,92 @@ +const { normalize, resolve } = require("path"); +const fs = require("fs"); +const vscode = require("vscode"); +const glob = require("glob"); + +let portableAppPath = process.env.VSCODE_PORTABLE; + +/** + * Get the filepath for the folder that contains the user's snippets files. + * @param {string} globalStoragePath - The absolute path for the VS Code installation. + * @returns {string} The path for the folder containg the user's snippets files. + */ +function getUserSnippetsHome(globalStoragePath) { + let path = ""; + + if (portableAppPath === undefined) { + path = resolve(globalStoragePath, "../../..", "User", "snippets").concat( + normalize("/") + ); + } else { + path = resolve(portableAppPath, "user-data", "User", "snippets").concat( + normalize("/") + ); + } + + return path; +} + +/** + * Get the filepath for all of the user's snippets files. + * @param {string} globalStoragePath - The absolute path for the VS Code installation. + * @returns {Promise} Promise with array of filepaths. + */ +async function getUserSnippetPaths(globalStoragePath) { + let userSnippetsHome = getUserSnippetsHome(globalStoragePath); + let list = []; + + let filenames = await fs.promises.readdir(userSnippetsHome).catch((error) => { + console.error(`No user snippets. ${error}`); + return list; + }); + + filenames.forEach((file) => { + let path = resolve(userSnippetsHome, file); + list.push(path); + }); + + return list; +} + +/** + * Get the filepaths for all of built-in VS Code snippets files. + * @return {Promise} Promise with array of filepaths. + */ +async function getAppSnippetPaths() { + let extensionRoot = resolve(vscode.env.appRoot, "extensions"); + + return new Promise((fufil, reject) => { + glob(`${extensionRoot}/**/snippets/*.code-snippets`, {}, (err, files) => { + if (err) { + reject(err); + } else { + fufil(files); + } + }); + }); +} + +/** + * Get the filepaths for all of the snippets files in the opened project. + * @return {Promise} Promise with array of filepaths. + */ +async function getProjectSnippetPaths() { + let root = vscode.workspace.workspaceFolders[0].uri.fsPath; + + return new Promise((fufil, reject) => { + glob(`${root}/.vscode/*.code-snippets`, { dot: true }, (err, files) => { + if (err) { + reject(err); + } else { + fufil(files); + } + }); + }); +} + +module.exports = { + getUserSnippetsHome, + getUserSnippetPaths, + getAppSnippetPaths, + getProjectSnippetPaths, +}; diff --git a/src/core/fetch.js b/src/core/fetch.js new file mode 100644 index 0000000..f3a9aff --- /dev/null +++ b/src/core/fetch.js @@ -0,0 +1,87 @@ +const SnippetsFile = require("../model/snippets-file"); +const env = require("./env"); +const parser = require("./parser"); +const { createExtensionObjects, toSnippetsArray } = require("./transform"); + +function fetch(globalStoragePath) { + /** + * Fetch the snippet files for the active project (workspace folder). + * @returns {Array} An array of `SnippetsFile` objects + */ + async function fetchProjectSnippetsFiles() { + let projectPaths = await env.getProjectSnippetPaths(); + let snippetsFiles = await fetchSnippetsFiles(projectPaths); + return snippetsFiles; + } + + /** + * Fetch the snippet files for the user. + * @returns {Array} An array of `SnippetsFile` objects + */ + async function fetchUserSnippetsFiles() { + let userPaths = await env.getUserSnippetPaths(globalStoragePath); + let snippetsFiles = fetchSnippetsFiles(userPaths); + return snippetsFiles; + } + + /** + * Fetch the snippet files for the app i.e. VS Code's builtin snippets. + * @returns {Array} An array of `SnippetsFile` objects + */ + async function fetchAppSnippetsFiles() { + let appPaths = await env.getAppSnippetPaths(); + let snippetsFiles = await fetchSnippetsFiles(appPaths); + return snippetsFiles; + } + + /** + * Fetch the installed extensions that have snippets files. + * @returns {Array} An array of `Extension` objects + */ + async function fetchExtensions() { + let extensions = createExtensionObjects(); + + for (let i = 0; i < extensions.length; i++) { + const extension = extensions[i]; + + let collectionPromised = extension.snippetsFiles.map((snippetsFile) => + parser.parse(snippetsFile.path) + ); + + // eslint-disable-next-line no-await-in-loop + let collection = await Promise.all(collectionPromised); + + collection.forEach((snippetsJson, index) => { + let snippetsArray = toSnippetsArray(snippetsJson); + extension.snippetsFiles[index].snippets = snippetsArray; + }); + } + + return extensions; + } + + return { + fetchProjectSnippetsFiles, + fetchUserSnippetsFiles, + fetchAppSnippetsFiles, + fetchExtensions, + }; +} + +async function fetchSnippetsFiles(paths) { + let array = []; + let parsedCollectionPromised = paths.map((path) => parser.parse(path)); + let collection = await Promise.all(parsedCollectionPromised); + + collection.forEach((snippetsJson, index) => { + if (snippetsJson !== undefined) { + let snippetsArray = toSnippetsArray(snippetsJson); + let snippetsFile = new SnippetsFile(paths[index], snippetsArray); + array.push(snippetsFile); + } + }); + + return array; +} + +module.exports = fetch; diff --git a/src/core/parser.js b/src/core/parser.js new file mode 100644 index 0000000..ad42764 --- /dev/null +++ b/src/core/parser.js @@ -0,0 +1,17 @@ +const fs = require("fs"); +const jsonc = require("jsonc-parser"); + +/** + * @async + * Asynchronously parse the entire contents of a file as JSON. The file can be formatted as JSON or + * JSONC (Microsoft's JSON with comments standard). + * @param {String} path A path to a file. If a URL is provided, it must use the `file:` protocol. + * @returns {Object} + */ +async function parse(path) { + let data = await fs.promises.readFile(path, { encoding: "utf-8" }); + let json = await jsonc.parse(data); + return json; +} + +module.exports = { parse }; diff --git a/src/core/transform.js b/src/core/transform.js new file mode 100644 index 0000000..bd13a45 --- /dev/null +++ b/src/core/transform.js @@ -0,0 +1,99 @@ +const vscode = require("vscode"); +const { resolve } = require("path"); +const Snippet = require("../model/snippet"); +const SnippetsFile = require("../model/snippets-file"); +const Extension = require("../model/extension"); + +/** + * A snippet is written in a file as a key-value pair where the key is the `name`, and + * the value is an object with the `prefix`, `body`, `description`, and `scope` fields. + * This function converts the key-value pair into a single object with all of those fields. + * @param {Object} snippetsObj JSON object of snippets file contents. + * @return {Object} An array with flattened `Snippet` objects + */ +function toSnippetsArray(snippetsObj) { + let array = []; + + Object.entries(snippetsObj).forEach(([key, value]) => { + let snippet = new Snippet( + key, + value.prefix, + value.body, + value.description, + value.scope + ); + array.push(snippet); + }); + + return array; +} + +/** + * Create `Extension` objects from VS Code's installed extensions that have snippets. The + * `package.json` of each extension is inspected to gather the set of snippets of the + * the extension. + * @return {Array} Array of `Extension` objects. + */ +function createExtensionObjects() { + let extensionObjs = []; + + vscode.extensions.all.forEach((extension) => { + let { packageJSON } = extension; + + if ( + packageJSON && + packageJSON.isBuiltin === false && + packageJSON.contributes && + packageJSON.contributes.snippets + ) { + let id = `${packageJSON.publisher}-${packageJSON.name}`; + let name = packageJSON.displayName; + + let { extensionPath } = extension; + + let snippetsFiles = transformFileEntries( + packageJSON.contributes.snippets, + extensionPath + ); + + let extensionObj = new Extension(id, name, extensionPath); + extensionObj.snippetsFiles = snippetsFiles; + + extensionObjs.push(extensionObj); + } + }); + + return extensionObjs; +} + +/** + * Extensions can have mutliple snippets file associated with multiple languages. These + * associations are defined as a collection of entries in the `package.json` in the form of + * `{ language : "javascript", path : "somepath/a.json" }`. Since a path can feature in more than one entry, + * duplication is an issue. This function transforms these file entries into unique `SnippetsFile` objects. + * @param {Array} fileEntries This is an array of objects. Each object has a `path` and `language` field. + * @returns {Array} An array of `SnippetsFile` objects. + */ +function transformFileEntries(fileEntries, extensionPath) { + let uniquePaths = new Map(); + + fileEntries.forEach((entry) => { + let absolutePath = resolve(extensionPath, entry.path); + + if (uniquePaths.has(absolutePath)) { + let snippetsFile = uniquePaths.get(absolutePath); + snippetsFile.addLanguage(entry.language); + + uniquePaths.set(absolutePath, snippetsFile); + } else { + let snippetsFile = new SnippetsFile(absolutePath); + snippetsFile.addLanguage(entry.language); + + uniquePaths.set(absolutePath, snippetsFile); + } + }); + + return [...uniquePaths.values()]; +} + +module.exports = { toSnippetsArray, createExtensionObjects }; diff --git a/src/environment.js b/src/environment.js deleted file mode 100644 index 748f840..0000000 --- a/src/environment.js +++ /dev/null @@ -1,172 +0,0 @@ -const { basename, normalize, resolve } = require("path"); -const fs = require("fs"); -// eslint-disable-next-line import/no-unresolved -const vscode = require("vscode"); -const glob = require("glob"); -const ExtensionCollection = require("./model/extension-collection"); - -/** - * Environment information. - */ -class Environment { - constructor(context) { - this.context = context; - this.os = process.platform; - this.portableAppPath = process.env.VSCODE_PORTABLE; - // @ts-ignore - this.userSnippetsDir = this.resolveUserSnippetsDir(); - this.userExtensionsDir = this.resolveUserExtensionsDir(); - } - - /** - * Get the filepath for User Snippets Directory. - */ - resolveUserSnippetsDir() { - let dir = ""; - if (this.portableAppPath === undefined) { - dir = resolve( - this.context.globalStoragePath, - "../../..", - "User", - "snippets" - ).concat(normalize("/")); - } else { - dir = resolve( - this.portableAppPath, - "user-data", - "User", - "snippets" - ).concat(normalize("/")); - } - - return dir; - } - - /** - * Get the filepath for User Extensions Directory. - */ - resolveUserExtensionsDir() { - let dir = ""; - if (this.portableAppPath === undefined) { - dir = resolve( - vscode.extensions.all.filter( - (extension) => !extension.packageJSON.isBuiltin - )[0].extensionPath, - ".." - ).concat(normalize("/")); - } else { - dir = resolve(this.portableAppPath, "extensions").concat(normalize("/")); - } - - return dir; - } - - /** - * Get the filepaths for all of the User Snippets files. - * @returns {Promise} Promise with array of filepaths. - */ - async getUserSnippetFilepaths() { - let list = []; - - let filenames = await fs.promises - .readdir(this.userSnippetsDir) - .catch((error) => { - console.error(`No user snippets. ${error}`); - return list; - }); - - filenames.forEach((file) => { - let path = resolve(this.userSnippetsDir, file); - list.push(path); - }); - - return list; - } - - /** - * Get the filepaths for all of App Snippets file. - * @return {Promise} Promise with array of filepaths. - */ - // eslint-disable-next-line class-methods-use-this - async getAppSnippetFilepaths() { - let extensionRoot = resolve(vscode.env.appRoot, "extensions"); - return new Promise((fufil, reject) => { - glob(`${extensionRoot}/**/snippets/*.code-snippets`, {}, (err, files) => { - if (err) { - reject(err); - } else { - fufil(files); - } - }); - }); - } - - /** - * Get the filepaths for all of the snippets files in the opened project. - * @return {Promise} Promise with array of filepaths. - */ - // eslint-disable-next-line class-methods-use-this - async getProjectSnippetFilepaths() { - let root = vscode.workspace.workspaceFolders[0].uri.fsPath - - return new Promise((fufil, reject) => { - glob(`${root}/.vscode/*.code-snippets`, { dot : true}, (err, files) => { - if (err) { - reject(err); - } else { - fufil(files); - } - }); - }); - } - - /** - * Get the filepaths for all of Extension Snippets file. - * @return {Promise} Promise with array of filepaths. - */ - // eslint-disable-next-line class-methods-use-this - async getExtensionSnippets() { - let array = []; - - vscode.extensions.all.forEach((extension) => { - let { packageJSON } = extension; - if ( - packageJSON && - packageJSON.isBuiltin === false && - packageJSON.contributes && - packageJSON.contributes.snippets - ) { - let extensionSnippets = new ExtensionCollection( - packageJSON.name, - packageJSON.displayName, - packageJSON.publisher - ); - packageJSON.contributes.snippets.forEach((snippet) => { - let path = resolve(extension.extensionPath, snippet.path); - extensionSnippets.addSnippetsFile(snippet.language, path); - }); - array.push(extensionSnippets); - } - }); - - return new Promise((fufil) => { - fufil(array); - }); - } - - /** - * Get the file name without the extension. - */ - static getFilename(path) { - let name = basename(path); - return name.split(".")[0]; - } - - /** - * Get the filepath for User Extensions Directory. - */ - getUserSnippetsDirPath() { - return this.userSnippetsDir; - } -} -module.exports = Environment; diff --git a/src/extension.js b/src/extension.js deleted file mode 100644 index 37dcecb..0000000 --- a/src/extension.js +++ /dev/null @@ -1,43 +0,0 @@ -// @ts-nocheck -/* eslint-disable import/no-unresolved, import/no-useless-path-segments, no-template-curly-in-string, no-unused-vars */ -const vscode = require("vscode"); -const View = require("./view/view"); -const Snippet = require("./model/snippet"); -const SnippetsEditor = require("./snippets-editor"); - -// this is included for webpack, so that it picks up the CSS file -const styles = require("../src/view/styles.css"); - -function activate(context) { - context.subscriptions.push( - vscode.commands.registerCommand("snippets-ranger.show", () => { - let view = new View(context); - view.show(); - }), - vscode.commands.registerCommand("snippets-ranger.add", () => { - let snippetsEditor = new SnippetsEditor(context); - let activeEditor = vscode.window.activeTextEditor; - - let bodyText = "${3}"; - if (activeEditor) { - let selectedText = activeEditor.document.getText( - activeEditor.selection - ); - if (selectedText.length > 0) { - bodyText = selectedText; - } - } - - let snippet = new Snippet("${1:enter a name}", "${2}", bodyText, "${4}"); - snippetsEditor.add(snippet); - }) - ); -} - -// this method is called when your extension is deactivated -function deactivate() {} - -module.exports = { - activate, - deactivate, -}; diff --git a/src/formatter.js b/src/formatter.js deleted file mode 100644 index 6d450fb..0000000 --- a/src/formatter.js +++ /dev/null @@ -1,86 +0,0 @@ -/** - * Formatter for snippet data. - */ -class Formatter { - static formatTitle(language) { - if ( - language === "html" || - language === "css" || - language === "xml" || - language === "php" || - language === "vb" || - language === "cpp" - ) { - return language.toUpperCase(); - } - return this.capitalize(language); - } - - /** - * Capitalize the first letter of the first word. - * @param {String} str String to capitalize. - */ - static capitalize(str) { - if (typeof str === "string") { - return str.replace(/^\w/, (c) => c.toUpperCase()); - } - return ""; - } - - /** - * Transforms HTML content that could be wrongfully interpreted as markup. - * @param {String} text The text to format. - */ - static escapeHtml(text) { - let str = text - .replace(/&/g, "&") - .replace(/"/g, """) - .replace(/'/g, "'") - .replace(//g, ">") - .replace(/\\/g, "\\") - .replace(/\r?\n/g, "
") - .replace(/\t/g, " "); - - return str; - } - - /** - * Escapes all th HTML content in the items of an array and concatenates it into a string - * that can be consumed by a web page. Each item is appended with a HTML line break (BR tag). - * @param {Array} array Array of values - */ - static escapeBody(array) { - let str = ""; - array.forEach((element) => { - str += Formatter.escapeHtml(element); - str += "
"; - }); - return str; - } - - static convertToArray(text, eolChar = "\n") { - if (text.includes(eolChar) === false) { - return [text]; - } - - let array = text.split(eolChar); - return array; - } - - /** - * Produces an ID from the text provided that can be used as an URL fragment. Does it in the same style as GitHub. - * Based on source code: https://github.com/jch/html-pipeline/blob/master/lib/html/pipeline/toc_filter.rb - * @param {string} text - The text to slugify - * @returns {string} The slug. - */ -static slugify(text) { - const PUNCTUATION_REGEXP = /[^\p{L}\p{M}\p{N}\p{Pc}\- ]/gu; - - let slug = text.trim().toLowerCase(); - slug = slug.replace(PUNCTUATION_REGEXP, "").replace(/ /g, "-"); - return slug; -} -} - -module.exports = Formatter; diff --git a/src/helper/format.js b/src/helper/format.js new file mode 100644 index 0000000..e217fdf --- /dev/null +++ b/src/helper/format.js @@ -0,0 +1,88 @@ +/** + * Convenience methods for formatting text and HTML. + */ + +/** + * Capitalize the first letter of the first word. + * @param {String} str String to capitalize. + */ +function capitalize(str) { + if (typeof str === "string") { + return str.replace(/^\w/, (c) => c.toUpperCase()); + } + return ""; +} + +/** + * Transforms HTML content that could be wrongfully interpreted as markup. + * @param {String} text The text to format. + */ +function escapeHtml(text) { + let str = text + .replace(/&/g, "&") + .replace(/"/g, """) + .replace(/'/g, "'") + .replace(//g, ">") + .replace(/\\/g, "\\") + .replace(/\r?\n/g, "
") + .replace(/\t/g, " "); + + return str; +} + +/** + * Escapes all the HTML content in the items of an array and concatenates it into a string + * that can be consumed by a web page. Each item is appended with a HTML line break (BR tag). + * @param {string|Array} array Array of values + */ +function escapeBody(body) { + let str = ""; + + if (typeof body === "string") { + str = escapeHtml(body); + } else if (Array.isArray(body)) { + body.forEach((element) => { + str += escapeHtml(element); + str += "
"; + }); + } + + return str; +} + +/** + * Convert a string into an array. If it is a multi-line string, each line becomes an element. + * @param {string} text + * @returns + */ +function convertToArray(text) { + if (/\n|\r\n/gm.test(text) === false) { + return [text]; + } + + let array = text.split(/\n|\r\n/gm); + return array; +} + +/** + * Produces an ID from the text provided that can be used as an URL fragment. Does it in the same style as GitHub. + * Based on source code: https://github.com/jch/html-pipeline/blob/master/lib/html/pipeline/toc_filter.rb + * @param {string} text - The text to slugify + * @returns {string} The slug. + */ +function slugify(text) { + const PUNCTUATION_REGEXP = /[^\p{L}\p{M}\p{N}\p{Pc}\- ]/gu; + + let slug = text.trim().toLowerCase(); + slug = slug.replace(PUNCTUATION_REGEXP, "").replace(/ /g, "-"); + return slug; +} + +module.exports = { + capitalize, + escapeHtml, + escapeBody, + convertToArray, + slugify, +}; diff --git a/src/util.js b/src/helper/util.js similarity index 71% rename from src/util.js rename to src/helper/util.js index 47950ed..79ccc8f 100644 --- a/src/util.js +++ b/src/helper/util.js @@ -1,8 +1,9 @@ const vscode = require("vscode"); const fs = require("fs"); +const path = require("path"); /** - * If the file exists, it does nothing. If the file does not exist, it will create a new file with an empty object. + * If the file exists, it does nothing. If the file does not exist, it will create a new file with an empty object. */ async function createFileIfDoesNotExist(filePath) { try { @@ -12,6 +13,21 @@ async function createFileIfDoesNotExist(filePath) { } } +/** + * Get the end of line delimiter for the platform you are running on. It + * differs on windows and *nix platforms. + * @returns {string} + */ +function getEndOfLineDelimiter() { + let eol = "\n"; + + if (process.platform === "win32") { + eol = "\r\n"; + } + + return eol; +} + /** * Prompts the user to pick a language with a quickpicker. */ @@ -42,4 +58,5 @@ module.exports = { createFileIfDoesNotExist, askForLanguage, escapeStringRegexp, + getEndOfLineDelimiter, }; diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..aa05e9b --- /dev/null +++ b/src/main.js @@ -0,0 +1,43 @@ +/* eslint-disable no-template-curly-in-string */ +const vscode = require("vscode"); + +const fetch = require("./core/fetch"); +const View = require("./view/webview"); +const { addSnippet } = require("./actions/add"); + +// This is included for Webpack, so that it picks up the CSS file +// eslint-disable-next-line no-unused-vars +const styles = require("./view/styles.css"); + +async function activate(context) { + context.subscriptions.push( + vscode.commands.registerCommand("snippets-ranger.show", async () => { + let view = View(context); + + let fetcher = fetch(context.globalStoragePath); + + let projectSnippetsFiles = await fetcher.fetchProjectSnippetsFiles(); + let userSnippetsFiles = await fetcher.fetchUserSnippetsFiles(); + let appSnippetsFiles = await fetcher.fetchAppSnippetsFiles(); + let extensions = await fetcher.fetchExtensions(); + + view.load( + projectSnippetsFiles, + userSnippetsFiles, + appSnippetsFiles, + extensions + ); + }), + vscode.commands.registerCommand("snippets-ranger.add", async () => { + await addSnippet(); + }) + ); +} + +// this method is called when your extension is deactivated +function deactivate() {} + +module.exports = { + activate, + deactivate, +}; diff --git a/src/model/collection.js b/src/model/collection.js deleted file mode 100644 index 22aaa5f..0000000 --- a/src/model/collection.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Snippets for a particular programming language. - */ -class Collection { - constructor(path, type, scoped, snippets, language = "" ) { - this.path = path; - this.type = type; - this.scoped = scoped; - this.snippets = snippets; - this.language = language.toLowerCase(); - } -} - -module.exports = Collection; diff --git a/src/model/extension-collection.js b/src/model/extension-collection.js deleted file mode 100644 index e73a828..0000000 --- a/src/model/extension-collection.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Snippets for a particular extension. An Extension can have snippets declared in - * different files. One snippet file can be associated with 1 or more languages. - */ -class ExtensionCollection { - constructor(name, displayName, publisher) { - this.name = name; - this.displayName = displayName; - this.publisher = publisher; - this.id = `${publisher}.${name}`; - this.snippets = []; - } - - /** - * - * @param {String} language The programming language associated with the file. - * @param {String} path The absolute file path for the snippet file. - */ - addSnippetsFile(language, path) { - let matched = false; - this.snippets.forEach((snippet, index) => { - if (path === snippet.path) { - this.snippets[index].languages.add(language); - matched = true; - } - }); - - if (matched === false) { - let languagesSet = new Set(); - languagesSet.add(language); - this.snippets.push({ languages: languagesSet, path, snippets: [] }); - } - } -} - -module.exports = ExtensionCollection; diff --git a/src/model/extension.js b/src/model/extension.js new file mode 100644 index 0000000..0679e6a --- /dev/null +++ b/src/model/extension.js @@ -0,0 +1,18 @@ +function addSnippetsFile(snippetsFile) { + this.snippetsFiles.push(snippetsFile); +} + +/* A VS Code extension */ +function Extension(id, name = "", path = "") { + let snippetsFiles = []; + + return { + id, + name, + path, + snippetsFiles, + addSnippetsFile, + }; +} + +module.exports = Extension; diff --git a/src/model/snippet.js b/src/model/snippet.js index 5d8ba3f..6984e83 100644 --- a/src/model/snippet.js +++ b/src/model/snippet.js @@ -1,73 +1,93 @@ -/* eslint-disable no-underscore-dangle */ -const formatter = require("../formatter"); - -/** - * VS Code Snippet. - */ -class Snippet { - constructor(name = "", prefix = "", body = [], description = "", scope = "") { - this.name = name; - this.prefix = prefix; - this.description = description; // optional field in source JSON file - this.body = body; // a string or array is permitted in source JSON file - this.scope = scope; // comma-separated list of languages - - // ensures no formatting issues when toString() is used - this.eol = "\n"; - if (process.platform === "win32") { - this.eol = "\r\n"; - } - } - - set name(newName) { - this._name = newName; - } - - get name() { - return this._name; - } - - set prefix(newPrefix) { - this._prefix = newPrefix; - } - - get prefix() { - return this._prefix; - } - - set description(newDesc) { - this._description = newDesc; - } - - get description() { - return this._description; - } - - set body(newBody) { - if (typeof newBody === "object") { - // array - this._body = newBody; - } else if (typeof newBody === "string") { - this._body = formatter.convertToArray(newBody, this.eol); - } - } - - get body() { - return this._body; - } - - set scope(newScope) { - this._scope = newScope; - } - - get scope() { - return this._scope; - } - - toString() { - // prettier-ignore - return `${this.eol}${JSON.stringify(this.name)} : {${this.eol}\t"prefix": ${JSON.stringify(this.prefix)},${this.eol}\t"body": ${JSON.stringify(this.body)},${this.eol}\t"description": ${JSON.stringify(this.description)}${this.eol}\t"scope": ${JSON.stringify(this.scope)}${this.eol}}`; - } -} - -module.exports = Snippet; +const format = require("../helper/format"); +const util = require("../helper/util"); + +/** + * The body can be a string or an array. This formats it to be an array internally always. + * @param {*} body - The string to format + * @param {string} [eol="\n"] - The end of line characters look to use for tokenization + * @returns {string} + * */ +function formatBody(body) { + let formatted = body; + + if (typeof body === "string") { + formatted = format.convertToArray(body); + } + + return formatted; +} + +/** + * The prefix can be a string or an array. This formats it to be an array internally always. + * @param {*} prefix - The string to format + * @param {string} [eol="\n"] - The end of line delimiter look to use for tokenization + * @returns {string} + * */ +function formatPrefix(prefix) { + let formatted = prefix; + + if (typeof prefix === "string") { + formatted = format.convertToArray(prefix); + } + + return formatted; +} + +/** + * Sort the languages and normalize the whitespace of the `scope` field. + * @param {string} scope + * @returns {string} + */ +function formatScope(scope) { + let formatted; + + let items = scope.split(","); + let nonblankItems = items.filter((item) => item.trim().length > 0); + let trimmedItems = nonblankItems.map((item) => item.trim()); + trimmedItems.sort(); + + formatted = trimmedItems.join(", "); + + return formatted; +} + +/** + * A code snippet. Code snippets are templates that make it easier to enter repeating code patterns. + */ +function Snippet( + name = "", + prefix = [], + body = [], + description = "", + scope = "" +) { + let formattedPrefix = formatPrefix(prefix); + let formattedBody = formatBody(body); + let formattedScope = formatScope(scope); + let endOfLineDelimiter = util.getEndOfLineDelimiter(); + + return { + name, + description, + set prefix(newPrefix) { + formattedPrefix = formatPrefix(newPrefix); + }, + get prefix() { + return formattedPrefix; + }, + set body(newBody) { + formattedBody = formatBody(newBody); + }, + get body() { + return formattedBody; + }, + set scope(newScope) { + formattedScope = formatScope(newScope); + }, + get scope() { + return formattedScope; + }, + }; +} + +module.exports = Snippet; diff --git a/src/model/snippets-file.js b/src/model/snippets-file.js new file mode 100644 index 0000000..2ae546b --- /dev/null +++ b/src/model/snippets-file.js @@ -0,0 +1,66 @@ +const { basename } = require("path"); + +/** + * Get the title of the snippet file. The title is the file name of the snippet file without + * the file extension. + * @returns {string} + */ +const getTitle = function () { + let name = basename(this.path); + return name.split(".")[0]; +}; + +/** + * Get the filename of the snippet file + * @returns {string} + */ +const getFileName = function () { + return basename(this.path); +}; + +/** + * Checks if the snippet file contains a snippet that the `scope` field populated. + * @returns {boolean} + */ +const isScoped = function () { + let scoped = false; + + const result = this.snippets.find( + ({ scope }) => scope !== undefined && scope !== "" + ); + + if (result !== undefined) { + scoped = true; + } + + return scoped; +}; + +/** + * A file that contain code snippets. + */ +function SnippetsFile(path = "", snippets = []) { + let languages = new Set(); + + return { + path, + snippets, + getTitle, + getFileName, + isScoped, + addLanguage(language) { + languages.add(language); + }, + removeLanguage(language) { + languages.delete(language); + }, + getLanguages() { + return [...languages]; + }, + setLanguages(newLanguages) { + languages = new Set(newLanguages); + }, + }; +} + +module.exports = SnippetsFile; diff --git a/src/snippets-editor.js b/src/snippets-editor.js deleted file mode 100644 index 4ae6eff..0000000 --- a/src/snippets-editor.js +++ /dev/null @@ -1,68 +0,0 @@ -// @ts-nocheck -/* eslint-disable import/no-unresolved, no-useless-escape, prefer-destructuring, no-template-curly-in-string */ -const vscode = require("vscode"); -const fs = require("fs"); -const Window = require("./window"); -const Util = require("./util"); -const SnippetsFetcher = require("./snippets-fetcher"); - -/** - * Responsible for adding new snippets it to a user snippet file of the user's choosing. - */ -class SnippetsEditor { - constructor(context) { - this.context = context; - this.window = new Window(context); - } - - /** - * @async - * Add a new snippet to a snippet file based on what the user selects from a quickpick. - * * @param {Snippet} snippet The snippet you want to add. - */ - async add(snippet) { - // if a global snippets file is created or no option is chosen, `selected` is undefined. otherwse, it is true - let selected = await vscode.commands.executeCommand( - "workbench.action.openSnippets" - ); - - let editor = vscode.window.activeTextEditor; - - // if user didnt selected an option - if ( - selected === undefined && - editor.document.fileName.endsWith(".code-snippets") === false - ) { - return; - } - - // default document language is JSON which is a bug! - await vscode.languages.setTextDocumentLanguage(editor.document, "jsonc"); - - let range = new vscode.Range(0, 1, 0, 1); - let snippetString = `${snippet.toString()},`; - - editor.insertSnippet(new vscode.SnippetString(snippetString), range); - } - - /** - * @async - * Delete a snippet from a snippet file. - * @param {vscode.Uri} uri Uri of snippet file - * @param {String} snippetName The name of the snippet to delete - * @returns {Promise} The TextEditor that contains the user snippets document. - */ - async deleteSnippet(uri, snippetName) { - let text = await SnippetsFetcher.getData(uri.fsPath); - - let escapedSnippetName = Util.escapeStringRegexp(snippetName); - let regex = new RegExp( - `[\r\n]*?"${escapedSnippetName}".*?:.*?\\{.*?\\},{0,1}`, - "ms" - ); - let newText = text.replace(regex, ""); - await fs.promises.writeFile(uri.fsPath, newText); - } -} - -module.exports = SnippetsEditor; diff --git a/src/snippets-fetcher.js b/src/snippets-fetcher.js deleted file mode 100644 index c124916..0000000 --- a/src/snippets-fetcher.js +++ /dev/null @@ -1,179 +0,0 @@ -const fs = require("fs"); -const jsonc = require("jsonc-parser"); -const Environment = require("./environment"); -const Collection = require("./model/collection"); -const Snippet = require("./model/snippet"); - -/** - * Fetch the Snippets from the file system. - */ -class SnippetsFetcher { - constructor(context) { - this.context = context; - this.env = new Environment(this.context); - } - - /** - * Get the snippets from the files as JSON objects. - * @param {Array} filepaths The filepaths for the files you want to extract snippets from. - * @param {String} type The type of snippets you are seeking. Can be "user", "app", "project", or "extension". - * @returns {Promise} A Promise with an array of JSON objects. - */ - async createSnippetsCollection(filepaths, type) { - let jsonObjects = await SnippetsFetcher.getObjectArray(filepaths); - let array = []; - - jsonObjects.forEach((obj, index) => { - if (obj !== undefined) { - let flatSnippets = this.flattenSnippets(obj); - let language = Environment.getFilename(filepaths[index]); - let scoped = hasScopeField(flatSnippets); - - let snippetsCollection = new Collection( - filepaths[index], - type, - scoped, - flatSnippets, - language - ); - array.push(snippetsCollection); - } - }); - return array; - } - - /** - * A snippet is written in a file as a key-value pair where the key is the `name`, and - * the value is an object with the `prefix`, `body`, and `description` fields. - * This function converts the key-value pair into a single object with those four fields. - * @param {Object} snippets JSON object of snippets file contents. - * @return {Object} An array with flattened snippets objects - */ - flattenSnippets(snippets) { - let flatSnippets = []; - - for (let [key, value] of Object.entries(snippets)) { - let { prefix, body, description, scope } = value; - let flatSnippet = new Snippet(key, prefix, body, description, scope); - flatSnippets.push(flatSnippet); - } - return flatSnippets; - } - - /** - * Get all of the ExtensionSnippets. The actual file data for snippet file is an embedded JSON object. - * @returns {Promise} A Promise with an array of ExtensionSnippets. - */ - async getExtensionSnippetsCollection() { - let extensionSnippetsArray = await this.env.getExtensionSnippets(); - let modifiedSnippetsArray = extensionSnippetsArray.map( - this.fetchExtensionSnippets.bind(this) - ); - return Promise.all(modifiedSnippetsArray).then(() => extensionSnippetsArray); - } - - async fetchExtensionSnippets(extensionSnippets) { - let promises = extensionSnippets.snippets.map(async (snippet) => { - let data = await SnippetsFetcher.getObject(snippet.path); - - if (data !== undefined) { - let flatSnippets = this.flattenSnippets(data); - // eslint-disable-next-line no-param-reassign - snippet.snippets = flatSnippets; - } - return snippet; - }); - - return Promise.all(promises); - } - - /** - * Get all of the User snippets as JSON objects. - * @returns {Promise} A Promise with an array of JSON objects. - */ - async getUserSnippetsCollection() { - let paths = await this.env.getUserSnippetFilepaths(); - return this.createSnippetsCollection(paths, "user"); - } - - /** - * Get all of the project's snippets as JSON objects. - * @returns {Promise} A Promise with an array of JSON objects. - */ - async getProjectSnippetsCollection() { - let paths = await this.env.getProjectSnippetFilepaths(); - - return this.createSnippetsCollection(paths, "project"); - } - - /** - * Get all of the App snippets as JSON objects. - * @returns {Promise} A Promise with an array of JSON objects. - */ - async getAppSnippetsCollection() { - let paths = await this.env.getAppSnippetFilepaths(); - return this.createSnippetsCollection(paths, "app"); - } - - /** - * @static - * @async - * Get the contents of the files. - * @param {Array} filepaths - * @returns {Promise} A Promise with an array of the file contents. - */ - static async getDataArray(filepaths) { - return Promise.all(filepaths.map((f) => fs.promises.readFile(f, "utf-8"))); - } - - /** - * @async - * @static - * Get the contents of the file. - * @param {String} filepath - * @returns {Promise} A Promise with the file contents. - */ - static async getData(filepath) { - return fs.promises.readFile(filepath, { encoding: "utf-8" }); - } - - /** - * Get the contents of the files as JSON objects. The files can be JSON or JSONC - * files (Microsoft JSON with comments standard). - * @param {Array} filepaths - * @returns {Promise} A Promise with an array of JSON objects. - */ - static async getObjectArray(filepaths) { - let data = await SnippetsFetcher.getDataArray(filepaths); - let json = data.map((d) => jsonc.parse(d)); - return Promise.all(json); - } - - /** - * @async - * @static - * Get the contents of the file as JSON objects. The files can be JSON or - * JSONC files (Microsoft JSON with comments standard). - * @param {String} filepath - * @returns {Promise} A Promise with an array of JSON objects. - */ - static async getObject(filepath) { - let data = await SnippetsFetcher.getData(filepath); - let json = await jsonc.parse(data); - return json; - } -} - -function hasScopeField(array){ - let has = false; - - const result = array.find(({ scope }) => scope !== undefined && scope !== "" ); - - if(result !== undefined){ - has = true; - } - - return has; -} - -module.exports = SnippetsFetcher; diff --git a/src/view/category-section.js b/src/view/category-section.js new file mode 100644 index 0000000..5807e1c --- /dev/null +++ b/src/view/category-section.js @@ -0,0 +1,65 @@ +let { + createFileSection, + createExtensionFileSection, +} = require("./file-section"); +let format = require("../helper/format"); + +const notFoundHTML = `

Oucho Gaucho! 🌵 Nothing to round up! 🤠

`; + +/** + * Creates the HTML for a section for a category of snippets e.g. "project" for snippets defined in + * the currently opened project. + * @param {SnippetsFile} snippetsFile - The snippets file you want the section based on. + * @param {string} category - The category of snippets. Examples are: project, user, app. + * @returns {string} The HTML for the section + */ +let createCategorySection = (snippetsFiles, category) => { + let title = `${format.capitalize(category)} Snippets`; + let opening = `

${title}

`; + + let section = opening; + + snippetsFiles.forEach((snippetFile) => { + section += createFileSection(snippetFile); + }); + + if (section === opening) { + section += notFoundHTML; + } + + section += "
"; + + return section; +}; + +/** + * Creates the HTML for a section for snippets defined in installed extensions. + * @param {Array} extensions - An array of `Extension` objects. + * @returns {string} The HTML for the section + */ +let createExtensionCategorySection = (extensions) => { + let opening = `

Extension Snippets

`; + + let section = opening; + + extensions.forEach((extension) => { + let id = format.slugify(extension.id); + section += `

${extension.name}

`; + + extension.snippetsFiles.forEach((snippetsFile) => { + section += createExtensionFileSection(snippetsFile); + }); + + section += `
`; + }); + + if (section === opening) { + section += notFoundHTML; + } + + section += "
"; + + return section; +}; + +module.exports = { createCategorySection, createExtensionCategorySection }; diff --git a/src/view/file-section.js b/src/view/file-section.js new file mode 100644 index 0000000..ec88d07 --- /dev/null +++ b/src/view/file-section.js @@ -0,0 +1,98 @@ +const { createSnippetsTable } = require("./snippets-table"); +const format = require("../helper/format"); + +/** + * Creates the HTML for a section for the snippets contained in a file. + * @param {SnippetsFile} snippetsFile The snippets file you want the section based on. + * @param {string} category The category of the snippets e.g "project". + * @returns {string} The HTML for the section + */ +const createFileSection = (snippetsFile) => { + let html = ""; + + if (snippetsFile !== undefined) { + html += `
`; + + html += `

${snippetsFile.getFileName()}

`; + + html += createViewSourceButton(snippetsFile.path); + html += `
`; + + let id = format.slugify(snippetsFile.path); + html += `
`; + + if (snippetsFile.snippets.length > 0) { + html += createSnippetsTable(snippetsFile); + } else { + html += `

No snippets.

`; + } + + html += `
`; + } + + return html; +}; + +/** + * Creates the HTML for a section for the snippets contained in a file that is defined in an extension. + * @param {SnippetsFile} snippetsFile The snippets file you want the section based on. + * @returns {string} The HTML for the section + */ +const createExtensionFileSection = (snippetsFile) => { + let html = ""; + + if (snippetsFile !== undefined) { + html += `
`; + html += `

${snippetsFile.getFileName()}

`; + + html += createViewSourceButton(snippetsFile.path); + + let languageList = createLanguageList(snippetsFile); + html += `
Languages available in: ${languageList}.
`; + + let id = format.slugify(snippetsFile.path); + html += `
`; + + if (snippetsFile.snippets.length > 0) { + html += createSnippetsTable(snippetsFile); + } else { + html += `

No snippets.

`; + } + + html += `
`; + } + + return html; +}; + +/** + * Create the HTML for a "view source" button that opens a snippet file. + * @param {string} path - the path to the snippet file + * @returns {string} - the HTML for the button + */ +function createViewSourceButton(path) { + let uri = encodeURIComponent(path); // prevents funny business with charcters especially with slashes + let html = ``; + return html; +} + +/** + * Create a `ul` of the languages associated with a snippets file. + * @param {SnippetsFile} snippetsFile - The snippets file you want to create the list from + */ +function createLanguageList(snippetsFile) { + let html = `
    `; + + snippetsFile + .getLanguages() + .sort() + .forEach((language) => { + html += `
  • ${language}
  • `; + }); + + html += `
`; + + return html; +} + +module.exports = { createFileSection, createExtensionFileSection }; diff --git a/src/view/snippets-table.js b/src/view/snippets-table.js new file mode 100644 index 0000000..2b122ef --- /dev/null +++ b/src/view/snippets-table.js @@ -0,0 +1,95 @@ +/* eslint-disable class-methods-use-this */ +const format = require("../helper/format"); + +/** + * Create a HTML `table` that displays the snippet collection. + * @param {SnippetsFile} snippetsFile - The `SnippetFile` to base the table on + * @returns {string} The HTML `table` + */ +const createSnippetsTable = (snippetsFile) => { + let html = ""; + let opening = ``; + } else { + opening += `>`; + } + + let head = createTableHead(snippetsFile); + let body = createTableBody(snippetsFile); + let closing = `
`; + + html = `${opening}${head}${body}${closing}`; + + return html; +}; + +/** + * Create the `thead` section for the `SnippetsFile` + */ +const createTableHead = (snippetsFile) => { + let html = `PrefixNameDescriptionBody`; + + if (snippetsFile.isScoped() === true) { + html += `Scope`; + } + + html += `Action`; + + return html; +}; + +/** + * Create the `tbody` section for the `SnippetsFile` + */ +const createTableBody = (snippetsFile) => { + // prevents funny business with charcters especially with slashes + let uri = encodeURIComponent(snippetsFile.path); + + let body = ""; + + snippetsFile.snippets.forEach((snippet) => { + let editIcon = ``; + let editButton = ``; + + let deleteIcon = ``; + let deleteButton = ``; + + body += ``; + body += `${createPrefixList(snippet.prefix)}`; + body += `${snippet.name}`; + body += `${snippet.description}`; + body += ""; + body += format.escapeBody(snippet.body); + body += ""; + + if (snippetsFile.isScoped() === true) { + body += `${snippet.scope}`; + } + + body += `${editButton}${deleteButton}`; + }); + + body += ``; + + return body; +}; + +function createPrefixList(prefix) { + let list = prefix; + + if (Array.isArray(prefix)) { + list = `
    `; + + prefix.forEach((item) => { + list += `
  • ${item}
  • `; + }); + + list += `
`; + } + + return list; +} + +module.exports = { createSnippetsTable }; diff --git a/src/view/styles.css b/src/view/styles.css index b77ecce..1a7dda7 100644 --- a/src/view/styles.css +++ b/src/view/styles.css @@ -1,426 +1,430 @@ -:root { - --body-bg-color-light-mode: rgb(255, 255, 255); - --body-bg-color-dark-mode: #292a2b; - --body-bg-color-contrast-mode: rgb(0, 0, 0); - --body-color-light-mode: black; - --body-color-dark-mode: #e6e6e6; - --body-color-contrast-mode: rgb(255, 255, 255); - --toc-bg-light-mode: rgba(241, 241, 241, 0.15); - --toc-bg-dark-mode: #1f2020; - --toc-box-shadow-light-mode: -2px 2px 8px 1px rgba(214, 214, 214, 0.6); - --toc-box-shadow-dark-mode: -2px 2px 8px 1px #18171782; - --table-head-color-light-mode: rgb(246, 246, 246); - --table-head-color-dark-mode: #383a3b; - --table-divider-color-light-mode: rgb(201, 198, 198); - --table-divider-color-dark-mode: #a0a7aa; - --table-highlight-color-light-mode: #f0f71d2f; - --table-highlight-color-dark-mode: #ffffff05; - --code-color-light-mode: #7a5600; - --code-color-dark-mode: #d7ba7d; - --table-action-column-width: 80px; - --table-min-width: 800px; -} - -*, -*::before, -*::after { - box-sizing: border-box; -} - -body, -body.vscode-dark, -body.vscode-light, -body.vscode-high-contrast { - font-family: Roboto, "Open Sans", san-serif; - font-size: calc(16px + 0.15vw); - padding: 10px; - margin: 0 auto; - max-width: 1600px; - overflow-x: auto; -} - -#toc { - display: flex; - justify-content: center; - align-items: center; - flex-direction: column; - width: 90%; - max-width: 580px; - margin: 40px auto; - border-radius: 10px; -} - -section h2, -h3, -h4 { - font-family: var(--vscode-font-family); - margin: 0; - margin-block-end: 0; - position: -webkit-sticky; - position: -moz-sticky; - position: -ms-sticky; - position: -o-sticky; - position: sticky; - min-width: var(--table-min-width); -} - -section h2 { - top: 0; - z-index: 1000; - text-align: center; -} - -body.vscode-high-contrast #toc h2 { - color: var(--body-color-light-mode); -} - -h3 { - top: 1.8rem; - margin: 0.1rem 0; - z-index: 500; - line-height: 150%; - font-size: 1.4rem; - font-style: italic; -} - -h4 { - top: 3.5rem; - z-index: 400; - line-height: 150%; - font-size: 1.1rem; - padding: 0.5em 0; -} - -code { - font-family: var(--vscode-editor-font-family); - font-size: calc(14px + 0.15vw); -} - -.empty { - text-align: center; -} - -button { - font-family: inherit; - border-radius: 5px; - border: none; - cursor: pointer; -} - -#toTopLink { - --size: 25px; - display: none; - position: fixed; - top: 6px; - right: 10px; - z-index: 9999; - width: var(--size); - height: var(--size); - border-radius: 15px; - cursor: pointer; - box-shadow: 0px 3px 5px -1px rgba(0, 0, 0, 0.2), - 0px 6px 10px 0px rgba(0, 0, 0, 0.14), 0px 1px 18px 0px rgba(0, 0, 0, 0.12); -} - -.upIcon { - border-radius: inherit; -} - -@media (min-width: 1000px) { - body, - body.vscode-dark, - body.vscode-light, - body.vscode-high-contrast { - width: 90%; - } - - #toTopLink { - --size: 30px; - right: 6%; - } -} - -@media (min-width: 1600px) { - #toTopLink { - right: calc((100vw - 1592px) / 2); - } -} - -table { - table-layout: fixed; - min-width: var(--table-min-width); - width: 100%; - border-collapse: collapse; - word-break: break-word; - margin: 1em 0; -} - -th { - font-weight: 500; - position: -webkit-sticky; - position: -moz-sticky; - position: -ms-sticky; - position: -o-sticky; - position: sticky; - line-height: 150%; - top: 3.5rem; -} - -th, -td { - margin: 0; - padding: 10px 0; - text-align: left; -} - -td { - padding-right: 5px; - vertical-align: top; -} - -td:nth-child(1) { - font-family: var(--vscode-editor-font-family); -} - -th:nth-child(1), -td:nth-child(1) { - width: 15%; -} - -th:nth-child(2), -td:nth-child(2) { - width: 20%; - display: none; -} - -th:nth-child(3), -td:nth-child(3) { - width: 35%; -} - -th:nth-child(4), -td:nth-child(4) { - width: calc(50% - var(--table-action-column-width)); -} - -th:nth-child(5), -td:nth-child(5) { - width: var(--table-action-column-width); -} - -.scoped-table :is(th:nth-child(3), td:nth-child(3)) { - width: 25%; -} - -/* using percentage value breaks down here, maybe because of long words */ -.scoped-table :is(th:nth-child(5),td:nth-child(5)) { - width: clamp(120px, 13vw ,240px); -} - -.scoped-table :is(th:nth-child(6),td:nth-child(6)) { - width: var(--table-action-column-width); -} - -@media (min-width: 1000px) { - th:nth-child(1), - td:nth-child(1) { - width: 15%; - } - - th:nth-child(2), - td:nth-child(2) { - display: table-cell; - } - - th:nth-child(3), - td:nth-child(3) { - width: 25%; - } - - th:nth-child(4), - td:nth-child(4) { - width: calc(40% - var(--table-action-column-width)); - } - - .scoped-table :is(th:nth-child(2), td:nth-child(2)) { - width: 15%; - } - - .scoped-table :is(th:nth-child(3), td:nth-child(3)) { - width: 20%; - } -} - - -body.vscode-dark td, -body.vscode-high-contrast td { - border-bottom: 1px solid var(--table-divider-color-dark-mode); -} - -body.vscode-light th { - background-color: var(--table-head-color-light-mode); - border-bottom: 1px solid var(--table-divider-color-light-mode); -} - -body.vscode-light td { - border-bottom: 1px solid var(--table-divider-color-light-mode); -} - -body.vscode-light tr:hover { - background-color: var(--table-highlight-color-light-mode); -} - -body.vscode-light td:nth-child(1) { - color: var(--code-color-light-mode); -} - -body.vscode-dark th, -body.vscode-high-contrast th { - background-color: var(--table-head-color-dark-mode); - border-bottom: 1px solid var(--table-divider-color-dark-mode); -} - -body.vscode-dark tr:hover, -body.vscode-high-contrast tr:hover { - background-color: var(--table-highlight-color-dark-mode); -} - -body.vscode-dark td:nth-child(1), -body.vscode-high-contrast td:nth-child(1) { - color: var(--code-color-dark-mode); -} - -body.vscode-light { - background-color: var(--body-bg-color-light-mode); - color: var(--body-color-light-mode); -} - -body.vscode-light section h2, -body.vscode-light h3, -body.vscode-light h4 { - background-color: var(--body-bg-color-light-mode); - color: var(--body-color-light-mode); -} - -body.vscode-light #toc { - background-color: var(--toc-bg-light-mode); - box-shadow: var(--toc-box-shadow-light-mode); -} - -body.vscode-light code { - color: var(--code-color-light-mode); -} - -body.vscode-light .upIcon { - background-color: rgb(208 208 208); - opacity: 1; -} - -body.vscode-dark { - background-color: var(--body-bg-color-dark-mode); - color: var(--body-color-dark-mode); -} - -body.vscode-dark section h2, -body.vscode-dark h3, -body.vscode-dark h4 { - background-color: var(--body-bg-color-dark-mode); - color: var(--body-color-dark-mode); -} - -body.vscode-dark #toc, -body.vscode-high-contrast #toc { - background-color: var(--toc-bg-dark-mode); - box-shadow: var(--toc-box-shadow-dark-mode); - border: 1px #323333 solid; -} - -body.vscode-dark code, -body.vscode-high-contrast code { - color: var(--code-color-dark-mode); -} - -body.vscode-dark .upIcon, -body.vscode-high-contrast .upIcon { - background-color: var(--body-bg-color-light-mode); - fill: var(--body-color-light-mode); -} - -body.vscode-high-contrast { - background-color: var(--body-bg-color-contrast-mode); - color: var(--body-color-contrast-mode); -} - -body.vscode-high-contrast section h2, -body.vscode-high-contrast h3, -body.vscode-high-contrast h4 { - background-color: var(--body-bg-color-contrast-mode); - color: var(--body-color-contrast-mode); -} - -body.vscode-high-contrast #toc { - background-color: var(--body-bg-color-light-mode); -} - -section#extension div p { - margin-top: 1.5rem; -} - -section#extension th { - top: 6rem; -} - -a { - text-decoration: none; -} - -h1 { - text-align: center; -} - -.wrapper { - overflow-x: scroll; -} - -.sourceBtn { - margin: 0 0.25em; - margin-top: 2.25em; - padding: 0.75em; -} - -.actionBtn { - --size: calc(var(--table-action-column-width) / 2 - 5px); - padding: 0.6em; - width: var(--size); - height: var(--size); -} - -.editBtn { - margin-right: 5px; -} - -button:focus { - outline: 3px solid orange; -} - -body.vscode-light button { - color: black; - background-color: rgb(218, 218, 218); - box-shadow: 0 1px 3px 0 rgb(0 0 0 / 35%); -} - -body.vscode-dark button, -body.vscode-high-contrast button { - color: black; - background-color: white; - box-shadow: 0 1px 3px 0 rgb(0 0 0 / 20%); -} - -body.vscode-high-contrast button { - font-weight: bold; -} - -.gif { - display: block; - margin: 0 auto; -} +:root { + --body-bg-color-light-mode: hsl(0, 0%, 95%); + --body-bg-color-dark-mode: hsl(210, 2%, 16%); + --body-bg-color-contrast-mode: hsl(0, 0%, 0%); + --body-bg-color: var(--body-bg-color-dark-mode); + + --body-color-light-mode: hsl(0, 0%, 5%); + --body-color-dark-mode: hsl(0, 0%, 90%); + --body-color-contrast-mode: hsl(0, 0%, 100%); + --body-color: var(--body-color-dark-mode); + + --code-color-light-mode: #7a5600; + --code-color-dark-mode: #d7ba7d; + --code-color: var(--code-color-dark-mode); + + --button-bg-color-dark-mode: hsl(0, 3%, 80%); + --button-bg-color-light-mode: hsl(0, 3%, 75%); + --button-bg-color-contrast-mode: hsl(0, 3%, 100%); + --button-bg-color: var(--button-bg-color-dark-mode); + + --button-color-dark-mode: hsl(0, 3%, 10%); + --button-color-light-mode: hsl(0, 3%, 25%); + --button-color-contrast-mode: hsl(0, 3%, 0%); + --button-color: var(--button-color-dark-mode); + + --toc-bg-color-light-mode: hsla(0, 9%, 87%, 0.15); + --toc-bg-color-dark-mode: hsl(0, 0%, 14%); + --toc-bg-color-contrast-mode: var(--body-bg-color-light-mode); + --toc-bg-color: var(--toc-bg-color-dark-mode); + + --border-color-light-mode: hsl(0, 3%, 78%); + --border-color-dark-mode: hsl(198, 6%, 36%); + --border-color-contrast-mode: hsl(0, 3%, 100%); + --border-color: var(--border-color-dark-mode); + + --table-head-color-light-mode: hsl(200, 0%, 85%); + --table-head-color-dark-mode: hsl(200, 0%, 23%); + --table-head-color: var(--table-head-color-dark-mode); + + --table-highlight-color-light-mode: #f0f71d2f; + --table-highlight-color-dark-mode: #ffffff05; + --table-highlight-color: var(--table-highlight-color-dark-mode); + + --table-action-column-width: 80px; + --table-min-width: 800px; + + --h2-height: 3.35rem; + --file-section-header-height: 4.4rem; + --extension-h3-height: 4.3rem; + --extension-file-section-header-height: 6.4rem; +} + +:root body.vscode-high-contrast { + --body-color: var(--body-color-contrast-mode); + --body-bg-color: var(--body-bg-color-contrast-mode); + + --button-color: var(--button-color-contrast-mode); + --button-bg-color: var(--button-bg-color-contrast-mode); + + --border-color: var(--border-color-contrast-mode); + + --toc-bg-color: var(--toc-bg-color-contrast-mode); +} + +:root body.vscode-light { + --body-color: var(--body-color-light-mode); + --body-bg-color: var(--body-bg-color-light-mode); + + --button-color: var(--button-color-light-mode); + --button-bg-color: var(--button-bg-color-light-mode); + + --code-color: var(--code-color-light-mode); + + --border-color: var(--border-color-light-mode); + + --toc-bg-color: var(--toc-bg-color-light-mode); + + --table-head-color: var(--table-head-color-light-mode); + --table-highlight-color: var(--table-highlight-color-light-mode); +} + +*, +*::before, +*::after { + box-sizing: border-box; +} + +:focus-visible { + outline: orange dotted 0.25rem; +} + +body { + font-family: Roboto, "Open Sans", san-serif; + font-size: calc(16px + 0.15vw); + padding: 10px; + margin: 0 auto; + max-width: 1600px; + overflow-x: auto; + + color: var(--body-color); + background-color: var(--body-bg-color); +} + +@media (min-width: 1000px) { + body { + width: 90%; + } +} + +code { + font-family: var(--vscode-editor-font-family); + font-size: calc(14px + 0.15vw); + color: var(--code-color); +} + +a { + text-decoration: none; +} + +img { + display: block; + margin: 0 auto; +} + +/** headings **/ + +:is(h1, h2, h3, h4, h5) { + margin: 0; +} + +h1 { + font-size: 2rem; + text-align: center; +} + +h2 { + font-size: 1.8rem; +} + +h3 { + font-size: 1.6rem; +} + +h4 { + font-size: 1.4rem; +} + +/** table of contents **/ + +#toc { + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + + width: 90%; + max-width: 580px; + margin: 4rem auto; + padding: 1rem 0; + border-radius: 10px; + + background-color: var(--toc-bg-color); + border: 1px solid var(--border-color); +} + +body.vscode-high-contrast #toc { + color: black; +} + +/** major sections **/ + +section { + margin-block-end: 4rem; +} + +.file-section { + position: relative; + margin-block-end: 2.5rem; +} + +section h2, +section header, +section#extension h3, +section#extension header { + position: sticky; + margin: 0; + background-color: var(--body-bg-color); + font-family: var(--vscode-font-family); + min-width: var(--table-min-width); +} + +section h2 { + top: 0; + z-index: 1000; + margin-bottom: 0; + padding-block-start: 1.25rem; +} + +section:not(#extension) header, +section#extension h3 { + --padding-block-start: 1.5rem; + + top: var(--h2-height); + z-index: 500; + padding: var(--padding-block-start) 0 1rem 0; +} + +section:not(#extension) header { + display: flex; + align-items: center; + gap: 1rem; +} + +section#extension header { + top: calc(var(--h2-height) + var(--extension-h3-height)); + z-index: 400; + padding: 0.5rem 0; + + display: grid; + grid-template-columns: auto auto 1fr; + align-items: center; + column-gap: 1rem; +} + +section#extension header :is(p, div) { + grid-column: 1 / -1; + margin: 0; + padding: 1.25rem 0; +} + +.language-list { + display: inline-block; + list-style: none; + padding: 0; + margin: 0; +} + +.language-list li { + display: inline; + padding-inline-start: 0.1rem; +} + +.language-list li code { + font-size: 0.9em; +} + +.language-list li:not(:last-child) code::after { + content: ","; + color: var(--body-color); +} + +.bookmark { + position: absolute; + top: calc(var(--h2-height) * -1); +} + +section#extension .bookmark { + top: calc((var(--h2-height) + var(--extension-h3-height)) * -1); +} + +/** table styles **/ + +table { + table-layout: fixed; + min-width: var(--table-min-width); + width: 100%; + border-collapse: collapse; + word-break: break-word; +} + +.wrapper { + overflow-x: scroll; +} + +th, +td { + margin: 0; + padding: 10px 0; + text-align: left; +} + +thead { + position: sticky; + top: calc(var(--h2-height) + var(--file-section-header-height)); +} + +section#extension thead { + top: 14.1rem; +} + +th { + font-weight: 500; + line-height: 150%; + + background-color: var(--table-head-color); + border-bottom: 1px solid var(--border-color); +} + +td { + padding-inline-end: 0.25rem; + vertical-align: top; + border-bottom: 1px solid var(--border-color); +} + +.prefix-list { + list-style: none; + margin: 0; + padding: 0; +} + +.prefix-list li:not(:last-child) { + padding-block-end: 0.5rem; +} + +.prefix-list li:not(:last-child)::after { + content: ","; + font-weight: bold; +} + +tr:hover { + background-color: var(--table-highlight-color); +} + +th:nth-child(1), +td:nth-child(1) { + width: 15%; +} + +th:nth-child(2), +td:nth-child(2) { + width: 20%; + display: none; +} + +th:nth-child(3), +td:nth-child(3) { + width: 35%; +} + +th:nth-child(4), +td:nth-child(4) { + width: calc(50% - var(--table-action-column-width)); +} + +th:nth-child(5), +td:nth-child(5) { + width: var(--table-action-column-width); +} + +.scoped-table :is(th:nth-child(3), td:nth-child(3)) { + width: 25%; +} + +/* using percentage value breaks down here, maybe because of long words? */ +.scoped-table :is(th:nth-child(5), td:nth-child(5)) { + width: clamp(120px, 13vw, 240px); +} + +.scoped-table :is(th:nth-child(6), td:nth-child(6)) { + width: var(--table-action-column-width); +} + +@media (min-width: 1000px) { + th:nth-child(1), + td:nth-child(1) { + width: 15%; + } + + th:nth-child(2), + td:nth-child(2) { + display: table-cell; + } + + th:nth-child(3), + td:nth-child(3) { + width: 25%; + } + + th:nth-child(4), + td:nth-child(4) { + width: calc(40% - var(--table-action-column-width)); + } + + .scoped-table :is(th:nth-child(2), td:nth-child(2)) { + width: 15%; + } + + .scoped-table :is(th:nth-child(3), td:nth-child(3)) { + width: 20%; + } +} + +/** buttons **/ + +button { + font-family: inherit; + border-radius: 5px; + border: none; + cursor: pointer; + + color: var(--button-color); + background-color: var(--button-bg-color); + box-shadow: 0 1px 2px 0 hsl(0deg 0% 0% / 15%), 0 0 4px 0 hsl(0deg 0% 0% / 10%), + 0 0 0 1px hsl(0deg 0% 0% / 10%) inset; +} + +button svg { + fill: var(--button-color); +} + +.sourceBtn { + padding: 0.2rem 0.4rem 0.175rem 0.4rem; + font-size: 0.75rem; +} + +.actionBtn { + --size: calc(var(--table-action-column-width) / 2 - 5px); + + padding: 0.6em; + width: var(--size); + height: var(--size); +} + +.editBtn { + margin-right: 5px; +} + +body.vscode-high-contrast button { + font-weight: bold; +} diff --git a/src/view/table-of-contents.js b/src/view/table-of-contents.js index 4fc939c..fdd53c6 100644 --- a/src/view/table-of-contents.js +++ b/src/view/table-of-contents.js @@ -1,44 +1,76 @@ -/** - * A HTML Table of Contents created from data. - */ -class TableOfContents { - constructor(data) { - this.data = data; - } - - /** - * Get the Table of Contents as HTML. - */ - getTableOfContents() { - let html = `
-

Table of Contents

-
    -
  • Project Snippets
  • `; - html += this.createTableOfContentsEntry(this.projectIDs); - html += `
  • User Snippets
  • `; - html += this.createTableOfContentsEntry(this.userIDs); - html += `
  • Extension Snippets
  • `; - html += this.createTableOfContentsEntry(this.extensionIDs); - html += `
  • VS Code Snippets
  • `; - html += this.createTableOfContentsEntry(this.appIDs); - html += `
`; - return html; - } - - /** - * Get the Table of Contents entry for Extension snippets as HTML. - */ - createTableOfContentsEntry(array) { - let html = "
    "; - - array.forEach((obj) => { - html += `
  • ${obj.name}`; - }); - - html += "
"; - - return html; - } -} - -module.exports = TableOfContents; +const format = require("../helper/format"); + +/** + * Create a table of contents in HTML from the snippets files. + * @param {Array} projectSnippetsFiles - An array of `SnippetsFile` objects for the project (workspace) + * @param {Array} userSnippetsFiles - An array of `SnippetsFile` objects for the user + * @param {Array} appSnippetsFiles - An array of `SnippetsFile` objects for the app (VS Code) + * @param {Array} extensions - An array of `Extension` objects that have snippets + * @returns {string} + */ +const createTableOfContents = ( + projectSnippetsFiles = [], + userSnippetsFiles = [], + appSnippetsFiles = [], + extensions = [] +) => { + let html = ""; + let entries = ""; + + entries += createCategoryEntry("project", projectSnippetsFiles); + entries += createCategoryEntry("user", userSnippetsFiles); + entries += createExtensionEntry(extensions); + entries += createCategoryEntry("app", appSnippetsFiles); + + if (entries !== "") { + html = `

Table of Contents

    ${entries}
`; + } + + return html; +}; + +const createCategoryEntry = (category, snippetsFiles) => { + let html = ""; + let entries = ""; + + snippetsFiles.forEach((snippetsFile) => { + entries += createSnippetsFileEntry(snippetsFile); + }); + + if (entries !== "") { + let title = `${format.capitalize(category)} Snippets`; + html += `
  • ${title}
      `; + html += `${entries}
  • `; + } + + return html; +}; + +const createSnippetsFileEntry = (snippetsFile) => { + let id = format.slugify(snippetsFile.path); + return `
  • ${snippetsFile.getTitle()}
  • `; +}; + +const createExtensionEntry = (extensions) => { + let html = ""; + let entries = ""; + + extensions.forEach((extension) => { + let id = format.slugify(extension.id); + entries += `
  • ${extension.name}
      `; + + extension.snippetsFiles.forEach((snippetsFile) => { + entries += createSnippetsFileEntry(snippetsFile); + }); + + entries += "
  • "; + }); + + if (entries !== "") { + html += `
  • Extension Snippets
      ${entries}
  • `; + } + + return html; +}; + +module.exports = { createTableOfContents }; diff --git a/src/view/view.js b/src/view/view.js deleted file mode 100644 index 98abf7e..0000000 --- a/src/view/view.js +++ /dev/null @@ -1,455 +0,0 @@ -const vscode = require("vscode"); -const { basename } = require("path"); -const path = require("path"); -const SnippetsFetcher = require("../snippets-fetcher"); -const Formatter = require("../formatter"); -const Window = require("../window"); -const SnippetsEditor = require("../snippets-editor"); -const Collection = require("../model/collection"); - -const notFoundHTML = `

    Oucho Gaucho! 🌵 Nothing to round up! 🤠

    `; - -/** - * View for Snippet Ranger. - */ -class View { - constructor(context) { - this.context = context; - this.panel = vscode.window.createWebviewPanel( - "snippetView", - "Snippets Ranger", - vscode.ViewColumn.One, - { - enableScripts: true, - retainContextWhenHidden: true, - } - ); - - this.snippetsFetcher = new SnippetsFetcher(this.context); - - this.panel.webview.onDidReceiveMessage( - async (message) => { - // eslint-disable-next-line default-case - switch (message.command) { - case "openSnippetFile": { - // path is encoded, so must decode first! - let uri = vscode.Uri.file(decodeURIComponent(message.path)); - await vscode.window.showTextDocument(uri); - break; - } - case "editSnippet": { - // path is encoded, so must decode first! - let uri = vscode.Uri.file(decodeURIComponent(message.path)); - await Window.showSnippet(uri, message.snippetName); - break; - } - case "deleteSnippet": { - // path is encoded, so must decode first! - let uri = vscode.Uri.file(decodeURIComponent(message.path)); - - let snippetsEditor = new SnippetsEditor(context); - - await snippetsEditor.deleteSnippet(uri, message.snippetName); - break; - } - } - }, - {}, - this.context.subscriptions - ); - - this.userIDs = []; - this.extensionIDs = []; - this.appIDs = []; - this.projectIDs = []; - } - - /** - * Show the web view. - */ - async show() { - this.getLoadingWebviewContent().then((html) => { - this.panel.webview.html = html; - }); - - this.getWebviewContent().then((html) => { - this.panel.webview.html = html; - }); - } - - /** - * Get the HTML for the loading page. - */ - async getLoadingWebviewContent() { - const stylesSrc = this.getStylesheetWebviewUri(); - - let html = ` - - - - Snippet Ranger - - - -
    -

    Snippets Ranger

    - loading image -

    Rounding them up!

    -
    - `; - - return html; - } - - /** - * Get the HTML page for the webview. - */ - async getWebviewContent() { - const stylesSrc = this.getStylesheetWebviewUri(); - - let htmlStart = ` - - - - Snippet Ranger - - - -

    Snippets Ranger

    `; - let htmlEnd = ``; - - let upIcon = `Go to Table of Contents`; - - let userSection = await this.getUserSnippetsSection(); - let appSection = await this.getAppSnippetsSection(); - let extensionSection = await this.getExtensionSnippetsSection(); - let projectSection = await this.getProjectSnippetsSection(); - let toc = this.getTableOfContents(); // relies on IDs being set by methods above - - let scriptSrc = this.getScriptWebviewUri(); - let script = ``; - - return `${htmlStart}${toc}${projectSection}${userSection}${extensionSection}${appSection}${upIcon}${script}${htmlEnd}`; - } - - /** - * Creates the HTML output for the section for a snippets set associated with a language. - * It has a title and a table listing all of the snippets. - * @param {Collection} languageSnippets The collection you want the section for - * @param {String} type The type of snippets. Values can be "user" or "app". - */ - createLanguageSection(languageSnippets, type) { - let section = ""; - - if ( - languageSnippets !== undefined && - languageSnippets.snippets.length > 0 - ) { - section += "
    "; - let title = Formatter.formatTitle(languageSnippets.language); - let id = `${type}-${title}`; - section += `

    ${title}

    `; - - // encodeURIComponent prevents funny business with charcters especially with slashes - let uri = encodeURIComponent(languageSnippets.path); - section += `
    `; - - section += this.getSnippetsTable(languageSnippets); - section += `
    `; - - let idObj = { - id, - name: title, - }; - if (type === "user") { - this.userIDs.push(idObj); - } else if (type === "app") { - this.appIDs.push(idObj); - } - } - - return section; - } - - /** - * Creates the HTML output for the section for a snippets set associated with a file. - * It has a title and a table listing all of the snippets. - * @param {LanguageSnippets} languageSnippets The LanguageSnippets you want the section for - * @param {String} type The type of snippets. Values can be "user" or "app". - */ - createFileSection(collection) { - let section = ""; - - if ( - collection !== undefined && - collection.snippets.length > 0 - ) { - section += "
    "; - let title = basename(collection.path, ".code-snippets"); - let id = `${collection.type}-${Formatter.slugify(title)}`; - section += `

    ${title}

    `; - - // encodeURIComponent prevents funny business with charcters especially with slashes - let uri = encodeURIComponent(collection.path); - section += `
    `; - - section += this.getSnippetsTable(collection); - section += `
    `; - - let idObj = { - id, - name: title, - }; - - this.projectIDs.push(idObj); - - } - - return section; - } - - - /** - * Creates the HTML output for a set of snippets associated with a snippets file from - * an extension. There is a title, a list of all the associated languages, - * and a table listing all of the snippets. - * @param {ExtensionSnippets} snippets The snippets associated with a snippets file for an extension. - */ - createExtensionFileSection(snippets) { - let section = ""; - - if (snippets !== undefined) { - section += "
    "; - let title = basename(snippets.path); - section += `

    ${title}

    `; - // convert from set to array, then make it into comma-separated list - let languages = this.toUnorderedList(Array.from(snippets.languages)); - section += `

    Available in the following languages:

    ${languages}`; - - // encodeURIComponent prevents funny business with charcters especially with slashes - let uri = encodeURIComponent(snippets.path); - section += `
    `; - - section += this.getSnippetsTable(snippets); - section += `
    `; - } - return section; - } - - /** Create the HTML output for a collection of snippets. - * @param {Array} snippetsCollection Array of snippet objects. - */ - getSnippetsTable(snippetsCollection) { - let tableStart = ``; - - if (snippetsCollection.scoped === true) { - tableStart += ``; - } - - tableStart += ``; - const tableEnd = `
    PrefixNameDescriptionBodyScopeAction
    `; - let table = tableStart; - - // prevents funny business with charcters especially with slashes - let uri = encodeURIComponent(snippetsCollection.path); - - snippetsCollection.snippets.forEach((snippet, index) => { - let editIcon = ``; - let editButton = ``; - - let rowIndex = index + 1; - - let deleteIcon = ``; - let deleteButton = ``; - - table += ` - ${snippet.prefix} - ${snippet.name} - ${snippet.description}`; - table += ""; - table += Formatter.escapeBody(snippet.body); - table += ""; - - if (snippetsCollection.scoped === true) { - table += `${snippet.scope}` - } - - table += `${editButton}${deleteButton}`; - }); - - table += `${tableEnd}`; - return table; - } - - /** - * Get the user-defined snippets as HTML. - */ - async getUserSnippetsSection() { - let userSnippets = await this.snippetsFetcher.getUserSnippetsCollection(); - let opening = `

    User Snippets

    `; - let section = opening; - - userSnippets.forEach((element) => { - section += this.createLanguageSection(element, "user"); - }); - - if (section === opening) { - section += notFoundHTML; - } - - section += "
    "; - - return section; - } - - /** - * Get the app-defined snippets as HTML. - */ - async getAppSnippetsSection() { - let appSnippets = await this.snippetsFetcher.getAppSnippetsCollection(); - let section = `

    VS Code Snippets

    `; - appSnippets.forEach((element) => { - section += this.createLanguageSection(element, "app"); - }); - section += `
    `; - return section; - } - - /** - * Get the extension-defined snippets as HTML. - */ - async getExtensionSnippetsSection() { - return this.snippetsFetcher - .getExtensionSnippetsCollection() - .then((extensionSnippetsArray) => { - let opening = `

    Extension Snippets

    `; - let section = opening; - extensionSnippetsArray.forEach((extensionSnippetsObj) => { - let appID = Formatter.slugify(extensionSnippetsObj.id); - section += `

    ${extensionSnippetsObj.displayName}

    `; - - this.extensionIDs.push({ - id: appID, - name: extensionSnippetsObj.displayName, - }); - - extensionSnippetsObj.snippets.forEach((snippetsObj) => { - section += this.createExtensionFileSection(snippetsObj); - }); - }); - - if (section === opening) { - section += notFoundHTML; - } - - section += `
    `; - return section; - }); - } - - async getProjectSnippetsSection(){ - let projectSnippets = await this.snippetsFetcher.getProjectSnippetsCollection(); - - - let opening = `

    Project Snippets

    `; - let section = opening; - - projectSnippets.forEach((element) => { - section += this.createFileSection(element); - }); - - if (section === opening) { - section += notFoundHTML; - } - - section += `
    `; - return section; - } - - /** - * Get the webview-compliant URI for the loading image. - */ - getLoadingWebviewUri() { - const onDiskPath = vscode.Uri.file( - path.join(this.context.extensionPath, "img", "loading.gif") - ); - const stylesSrc = this.panel.webview.asWebviewUri(onDiskPath); - return stylesSrc; - } - - /** - * Get the webview-compliant URI for the main stylesheet. - */ - getStylesheetWebviewUri() { - const onDiskPath = vscode.Uri.file( - path.join(this.context.extensionPath, "dist", "styles.minified.css") - ); - const stylesSrc = this.panel.webview.asWebviewUri(onDiskPath); - return stylesSrc; - } - - /** - * Get the webview-compliant URI for the main script. - */ - getScriptWebviewUri() { - const onDiskPath = vscode.Uri.file( - path.join(this.context.extensionPath, "script", "main.js") - ); - const script = this.panel.webview.asWebviewUri(onDiskPath); - return script; - } - - /** - * Get the Table of Contents as HTML. - */ - getTableOfContents() { - let html = `
    -

    Table of Contents

    -
      -
    • Project Snippets
    • `; - html += this.createTableOfContentsEntry(this.projectIDs); - html += `
    • User Snippets
    • `; - html += this.createTableOfContentsEntry(this.userIDs); - html += `
    • Extension Snippets
    • `; - html += this.createTableOfContentsEntry(this.extensionIDs); - html += `
    • VS Code Snippets
    • `; - html += this.createTableOfContentsEntry(this.appIDs); - html += `
    `; - return html; - } - - /** - * Get the Table of Contents entry for Extension snippets as HTML. - */ - createTableOfContentsEntry(array) { - let html = "
      "; - - array.forEach((obj) => { - html += `
    • ${obj.name}`; - }); - - html += "
    "; - - return html; - } - - toUnorderedList(array) { - let html = `
      `; - - array.forEach((element) => { - html += `
    • ${element}
    • `; - }); - - html += `
    `; - - return html; - } -} - -module.exports = View; diff --git a/src/view/webview.js b/src/view/webview.js new file mode 100644 index 0000000..e79ffa7 --- /dev/null +++ b/src/view/webview.js @@ -0,0 +1,157 @@ +const vscode = require("vscode"); +const path = require("path"); +const { + createCategorySection, + createExtensionCategorySection, +} = require("./category-section"); +const { createTableOfContents } = require("./table-of-contents"); +const { deleteSnippet } = require("../actions/delete"); +const { editSnippet } = require("../actions/edit"); + +/** + * A view displaying the snippets on a user's system. + * + * @param {*} context - The extension context + */ +function View(context) { + let panel; + let head; + + init(); + + function init() { + show(); + addMessageHandlers(); + } + + /** + * Show the web view. + */ + function show() { + // createWebviewPanel shows a blank panel + panel = vscode.window.createWebviewPanel( + "snippetView", + "Snippets Ranger", + vscode.ViewColumn.One, + { + enableScripts: true, + retainContextWhenHidden: true, + } + ); + + head = createHead(); + + panel.webview.html = getLoadingStateHtml(); + } + + /** + * The message handlers respond to events from the webview. The events are + * triggered by `script/main.js` script. + */ + function addMessageHandlers() { + panel.webview.onDidReceiveMessage( + async (message) => { + if (message.command === "openSnippetFile") { + let uri = vscode.Uri.file(decodeURIComponent(message.path)); + + await vscode.window.showTextDocument(uri); + } else if (message.command === "editSnippet") { + let uri = vscode.Uri.file(decodeURIComponent(message.path)); + + await editSnippet(uri, message.snippetName); + } else if (message.command === "deleteSnippet") { + let uri = vscode.Uri.file(decodeURIComponent(message.path)); + + await deleteSnippet(uri, message.snippetName); + } + }, + {}, + context.subscriptions + ); + } + + /** + * Create the `head` for the document. + * @returns + */ + function createHead() { + let stylesheetLink = ``; + + let html = ` + ${stylesheetLink}Snippet Ranger`; + + return html; + } + + /** + * Get the HTML for the page in a loading state. A spinner animation is shown alongside the text + * "Rounding them up!". + * @returns {string} This is the html. + */ + function getLoadingStateHtml() { + let html = `${head} + +
    +

    Snippets Ranger

    + loading image +

    Rounding them up!

    +
    + `; + + return html; + } + + /** + * Get a webview-compliant URI for the provided paths + * @returns {vscode.Uri} The vscode uri. + */ + function convertToWebviewUri(...paths) { + const uri = vscode.Uri.file(path.join(context.extensionPath, ...paths)); + return panel.webview.asWebviewUri(uri); + } + + /** + * Load the data provided to update the view. + * + * @param {Array} projectSnippetsFiles - an array of `SnippetsFile` objects for the project + * @param {Array} userSnippetsFiles - an array of `SnippetsFile` objects for the user + * @param {Array} appSnippetsFiles - an array of `SnippetsFile` objects for the app (VS Code) + * @param {Array} extensions - an array of installed `Extension` objects that has snippets + */ + function load( + projectSnippetsFiles, + userSnippetsFiles, + appSnippetsFiles, + extensions + ) { + let html = `${head} +

    Snippets Ranger

    `; + html += createTableOfContents( + projectSnippetsFiles, + userSnippetsFiles, + appSnippetsFiles, + extensions + ); + html += createCategorySection(projectSnippetsFiles, "project"); + html += createCategorySection(userSnippetsFiles, "user"); + html += createExtensionCategorySection(extensions); + html += createCategorySection(appSnippetsFiles, "app"); + html += ``; + html += `
    `; + + panel.webview.html = html; + } + + return { load }; +} + +module.exports = View; diff --git a/src/window.js b/src/window.js deleted file mode 100644 index 2962151..0000000 --- a/src/window.js +++ /dev/null @@ -1,60 +0,0 @@ -// eslint-disable-next-line import/no-unresolved -const vscode = require("vscode"); -const path = require("path"); -const Util = require("./util"); -const Environment = require("./environment"); - -/** - * Convenience class for the window of the editor. - */ -class Window { - constructor(context) { - this.context = context; - this.env = new Environment(this.context); - } - - /** - * @async - * Open a user snippet file. The user is prompted to pick a language. - * @returns {Promise} The TextEditor that contains the user snippets document. - */ - async showUserSnippets(language) { - let dir = this.env.getUserSnippetsDirPath(); - let languageFile = `${language}.json`; - let languageFilePath = path.join(dir, languageFile); - await Util.createFileIfDoesNotExist(languageFilePath); - - let uri = vscode.Uri.file(decodeURIComponent(languageFilePath)); - let editor = await vscode.window.showTextDocument(uri); - return editor; - } - - /** - * @async - * Open a snippet file and jump to the snippet. If the snippet is not - * found, it will open the snippet file with the cursor on the first line. - * @returns {Promise} The TextEditor that contains the user snippets document. - */ - static async showSnippet(uri, snippetName) { - let textEditor = await vscode.window.showTextDocument(uri); - let doc = textEditor.document; - let text = doc.getText(); - - let escapedSnippetName = Util.escapeStringRegexp(snippetName); - let regex = new RegExp(`"${escapedSnippetName}".*?:.*?\\{`); - let match = regex.exec(text); - let index = 0; - - if (match !== null) { - index = match.index + 1; - } - - let position = textEditor.document.positionAt(index); - let range = new vscode.Range(position, position); - textEditor.revealRange(range, vscode.TextEditorRevealType.AtTop); - textEditor.selection = new vscode.Selection(position, position); - return textEditor; - } -} - -module.exports = Window; diff --git a/test/runTest.js b/test/runTest.js index 3023924..42bf877 100644 --- a/test/runTest.js +++ b/test/runTest.js @@ -1,22 +1,22 @@ -const path = require("path"); -const { runTests } = require("vscode-test"); - -async function main() { - try { - // The folder containing the Extension Manifest package.json - // Passed to `--extensionDevelopmentPath` - const extensionDevelopmentPath = path.resolve(__dirname, "../"); - - // The path to the extension test script - // Passed to --extensionTestsPath - const extensionTestsPath = path.resolve(__dirname, "./suite/index"); - - // Download VS Code, unzip it and run the integration test - await runTests({ extensionDevelopmentPath, extensionTestsPath }); - } catch (err) { - console.error("Failed to run tests"); - process.exit(1); - } -} - -main(); +const path = require("path"); +const { runTests } = require("vscode-test"); + +async function main() { + try { + // The folder containing the Extension Manifest package.json + // Passed to `--extensionDevelopmentPath` + const extensionDevelopmentPath = path.resolve(__dirname, "../"); + + // The path to the extension test script + // Passed to --extensionTestsPath + const extensionTestsPath = path.resolve(__dirname, "./suite/index"); + + // Download VS Code, unzip it and run the integration test + await runTests({ extensionDevelopmentPath, extensionTestsPath }); + } catch (err) { + console.error("Failed to run tests"); + process.exit(1); + } +} + +main(); diff --git a/test/sample-data/extension-snippets.json b/test/sample-data/extension-snippets.json new file mode 100644 index 0000000..8cac2bd --- /dev/null +++ b/test/sample-data/extension-snippets.json @@ -0,0 +1,2017 @@ +[ + { + "name": "vscode-markdownlint", + "displayName": "markdownlint", + "publisher": "DavidAnson", + "id": "DavidAnson.vscode-markdownlint", + "snippets": [ + { + "languages": {}, + "path": "/home/rob/.vscode-oss/extensions/davidanson.vscode-markdownlint-0.51.0-universal/snippets.json", + "snippets": [ + { + "_name": "insertMarkdownLintDisableComment", + "_prefix": "markdownlint-disable", + "_description": "Disables one or more rules by name (MD013), alias (line-length), or tag (whitespace). Multiple rules are space-delimited (MD018 MD019). If no rules are specified, all rules are disabled. Takes effect starting with the line the comment is on.", + "_body": [""], + "_scope": "", + "eol": "\n" + }, + { + "_name": "insertMarkdownLintEnableComment", + "_prefix": "markdownlint-enable", + "_description": "Enables one or more rules by name (MD013), alias (line-length), or tag (whitespace). Multiple rules are space-delimited (MD018 MD019). If no rules are specified, all rules are enabled. Takes effect starting with the line the comment is on.", + "_body": [""], + "_scope": "", + "eol": "\n" + }, + { + "_name": "insertMarkdownLintDisableFileComment", + "_prefix": "markdownlint-disable-file", + "_description": "Disables one or more rules by name (MD013), alias (line-length), or tag (whitespace). Multiple rules are space-delimited (MD018 MD019). If no rules are specified, all rules are disabled. Applies to the entire file.", + "_body": [""], + "_scope": "", + "eol": "\n" + }, + { + "_name": "insertMarkdownLintEnableFileComment", + "_prefix": "markdownlint-enable-file", + "_description": "Enables one or more rules by name (MD013), alias (line-length), or tag (whitespace). Multiple rules are space-delimited (MD018 MD019). If no rules are specified, all rules are enabled. Applies to the entire file.", + "_body": [""], + "_scope": "", + "eol": "\n" + }, + { + "_name": "insertMarkdownLintDisableLineComment", + "_prefix": "markdownlint-disable-line", + "_description": "Disables one or more rules by name (MD013), alias (line-length), or tag (whitespace). Multiple rules are space-delimited (MD018 MD019). If no rules are specified, all rules are disabled. Applies to the current line only.", + "_body": [""], + "_scope": "", + "eol": "\n" + }, + { + "_name": "insertMarkdownLintDisableNextLineComment", + "_prefix": "markdownlint-disable-next-line", + "_description": "Disables one or more rules by name (MD013), alias (line-length), or tag (whitespace). Multiple rules are space-delimited (MD018 MD019). If no rules are specified, all rules are disabled. Applies to the next line only.", + "_body": [""], + "_scope": "", + "eol": "\n" + }, + { + "_name": "insertMarkdownLintCaptureComment", + "_prefix": "markdownlint-capture", + "_description": "Captures the current rule configuration. Takes effect starting with the line the comment is on.", + "_body": [""], + "_scope": "", + "eol": "\n" + }, + { + "_name": "insertMarkdownLintRestoreComment", + "_prefix": "markdownlint-restore", + "_description": "Restores the most recently captured rule configuration. Defaults to the document's initial configuration. Takes effect starting with the line the comment is on.", + "_body": [""], + "_scope": "", + "eol": "\n" + }, + { + "_name": "insertMarkdownLintConfigureFileComment", + "_prefix": "markdownlint-configure-file", + "_description": "Configures one or more rules by name (MD013), alias (line-length), or tag (whitespace) using the same JSON format as the \"markdownlint.config\" object. Applies to the entire file.", + "_body": [ + "" + ], + "_scope": "", + "eol": "\n" + } + ] + } + ] + }, + { + "name": "markdown-snippets", + "displayName": "Markdown Snippets", + "publisher": "robole", + "id": "robole.markdown-snippets", + "snippets": [ + { + "languages": {}, + "path": "/home/rob/.vscode-oss/extensions/robole.markdown-snippets-0.9.1-universal/snippets/snippets.code-snippets", + "snippets": [ + { + "_name": "Insert task list", + "_prefix": "task", + "_description": "Insert task list", + "_body": ["- [${1| ,x|}] ${2:text}", "${0}"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Insert task list 2", + "_prefix": "task2", + "_description": "Insert task list with 2 tasks", + "_body": [ + "- [${1| ,x|}] ${2:text}", + "- [${3| ,x|}] ${4:text}", + "${0}" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Insert task list 3", + "_prefix": "task3", + "_description": "Insert task list with 3 tasks", + "_body": [ + "- [${1| ,x|}] ${2:text}", + "- [${3| ,x|}] ${4:text}", + "- [${5| ,x|}] ${6:text}", + "${0}" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Insert task list 4", + "_prefix": "task4", + "_description": "Insert task list with 4 tasks", + "_body": [ + "- [${1| ,x|}] ${2:text}", + "- [${3| ,x|}] ${4:text}", + "- [${5| ,x|}] ${6:text}", + "- [${7| ,x|}] ${8:text}", + "${0}" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Insert task list 5", + "_prefix": "task5", + "_description": "Insert task list with 5 tasks", + "_body": [ + "- [${1| ,x|}] ${2:text}", + "- [${3| ,x|}] ${4:text}", + "- [${5| ,x|}] ${6:text}", + "- [${7| ,x|}] ${8:text}", + "- [${9| ,x|}] ${10:text}", + "${0}" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Insert table", + "_prefix": "table", + "_description": "Insert table with 2 rows and 3 columns. First row is heading.", + "_body": [ + "| ${1:Column1} | ${2:Column2} | ${3:Column3} |", + "|-------------- | -------------- | -------------- |", + "| ${4:Item1} | ${5:Item1} | ${6:Item1} |", + "${0}" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Insert 2x1 table", + "_prefix": "2x1table", + "_description": "Insert table with 2 rows and 1 column. First row is heading.", + "_body": [ + "| ${1:Column1} |", + "|-------------- |", + "| ${2:Item1} |", + "${0}" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Insert 3x1 table", + "_prefix": "3x1table", + "_description": "Insert table with 3 rows and 1 column. First row is heading.", + "_body": [ + "| ${1:Column1} |", + "|-------------- |", + "| ${2:Item1} |", + "| ${3:Item2} |", + "${0}" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Insert 4x1 table", + "_prefix": "4x1table", + "_description": "Insert table with 4 rows and 1 column. First row is heading.", + "_body": [ + "| ${1:Column1} |", + "|-------------- |", + "| ${2:Item1} |", + "| ${3:Item2} |", + "| ${4:Item3} |", + "${0}" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Insert 5x1 table", + "_prefix": "5x1table", + "_description": "Insert table with 5 rows and 1 column. First row is heading.", + "_body": [ + "| ${1:Column1} |", + "|-------------- |", + "| ${2:Item1} |", + "| ${3:Item2} |", + "| ${4:Item3} |", + "| ${5:Item4} |", + "${0}" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Insert 2x2 table", + "_prefix": "2x2table", + "_description": "Insert table with 2 rows and 2 columns. First row is heading.", + "_body": [ + "| ${1:Column1} | ${2:Column2} |", + "|--------------- | --------------- |", + "| ${3:Item1.1} | ${4:Item2.1} |", + "${0}" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Insert 3x2 table", + "_prefix": "3x2table", + "_description": "Insert table with 3 rows and 2 columns. First row is heading.", + "_body": [ + "| ${1:Column1} | ${2:Column2} |", + "|--------------- | --------------- |", + "| ${3:Item1.1} | ${4:Item2.1} |", + "| ${5:Item1.2} | ${6:Item2.2} |", + "${0}" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Insert 4x2 table", + "_prefix": "4x2table", + "_description": "Insert table with 4 rows and 2 columns. First row is heading.", + "_body": [ + "| ${1:Column1} | ${2:Column2} |", + "|--------------- | --------------- |", + "| ${3:Item1.1} | ${4:Item2.1} |", + "| ${5:Item1.2} | ${6:Item2.2} |", + "| ${7:Item1.3} | ${8:Item2.3} |", + "${0}" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Insert 5x2 table", + "_prefix": "5x2table", + "_description": "Insert table with 5 rows and 2 columns. First row is heading.", + "_body": [ + "| ${1:Column1} | ${2:Column2} |", + "|--------------- | --------------- |", + "| ${3:Item1.1} | ${4:Item2.1} |", + "| ${5:Item1.2} | ${6:Item2.2} |", + "| ${7:Item1.3} | ${8:Item2.3} |", + "| ${9:Item1.4} | ${10:Item2.4} |", + "${0}" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Insert 2x3 table", + "_prefix": "2x3table", + "_description": "Insert table with 2 rows and 3 columns. First row is heading.", + "_body": [ + "| ${1:Column1} | ${2:Column2} | ${3:Column3} |", + "|---------------- | --------------- | --------------- |", + "| ${4:Item1.1} | ${5:Item2.1} | ${6:Item3.1} |", + "${0}" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Insert 3x3 table", + "_prefix": "3x3table", + "_description": "Insert table with 3 rows and 3 columns. First row is heading.", + "_body": [ + "| ${1:Column1} | ${2:Column2} | ${3:Column3} |", + "|---------------- | --------------- | --------------- |", + "| ${4:Item1.1} | ${5:Item2.1} | ${6:Item3.1} |", + "| ${7:Item1.2} | ${8:Item2.2} | ${9:Item3.2} |", + "${0}" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Insert 4x3 table", + "_prefix": "4x3table", + "_description": "Insert table with 4 rows and 3 columns. First row is heading.", + "_body": [ + "| ${1:Column1} | ${2:Column2} | ${3:Column3} |", + "|---------------- | --------------- | --------------- |", + "| ${4:Item1.1} | ${5:Item2.1} | ${6:Item3.1} |", + "| ${7:Item1.2} | ${8:Item2.2} | ${9:Item3.2} |", + "| ${10:Item1.3} | ${11:Item2.3} | ${12:Item3.3} |", + "${0}" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Insert 5x3 table", + "_prefix": "5x3table", + "_description": "Insert table with 5 rows and 3 columns. First row is heading.", + "_body": [ + "| ${1:Column1} | ${2:Column2} | ${3:Column3} |", + "|---------------- | --------------- | --------------- |", + "| ${4:Item1.1} | ${5:Item2.1} | ${6:Item3.1} |", + "| ${7:Item1.2} | ${8:Item2.2} | ${9:Item3.2} |", + "| ${10:Item1.3} | ${11:Item2.3} | ${12:Item3.3} |", + "| ${13:Item1.4} | ${14:Item2.4} | ${15:Item3.4} |", + "${0}" + ], + "_scope": "", + "eol": "\n" + } + ] + } + ] + }, + { + "name": "vue-vscode-snippets", + "displayName": "Vue VSCode Snippets", + "publisher": "sdras", + "id": "sdras.vue-vscode-snippets", + "snippets": [ + { + "languages": {}, + "path": "/home/rob/.vscode-oss/extensions/sdras.vue-vscode-snippets-3.1.1/snippets/vue.json", + "snippets": [ + { + "_name": "Vue Single File Component", + "_prefix": "vbase", + "_description": "Base for Vue File with SCSS", + "_body": [ + "", + "", + "", + "", + "" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Single File Component with SASS", + "_prefix": "vbase-sass", + "_description": "Base for Vue File with PostCSS", + "_body": [ + "", + "", + "", + "", + "" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Single File Component with LESS", + "_prefix": "vbase-less", + "_description": "Base for Vue File with PostCSS", + "_body": [ + "", + "", + "", + "", + "" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Single File Component with postcss", + "_prefix": "vbase-pcss", + "_description": "Base for Vue File with PostCSS", + "_body": [ + "", + "", + "", + "", + "" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Single File Component with Css", + "_prefix": "vbase-css", + "_description": "Base for Vue File with CSS", + "_body": [ + "", + "", + "", + "", + "" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Single File Component with Stylus", + "_prefix": "vbase-styl", + "_description": "Base for Vue File with Stylus", + "_body": [ + "", + "", + "", + "", + "" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Single File Component with Typescript", + "_prefix": "vbase-ts", + "_description": "Base for Vue File with Typescript", + "_body": [ + "", + "", + "", + "", + "" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Single File Component with No Style", + "_prefix": "vbase-ns", + "_description": "Base for Vue File with no styles", + "_body": [ + "", + "", + "" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Single File Component Composition API", + "_prefix": "vbase-3", + "_description": "Base for Vue File Composition API with SCSS", + "_body": [ + "", + "", + "", + "", + "" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Single File Component Setup Composition API", + "_prefix": "vbase-3-setup", + "_description": "Base for Vue File Setup Composition API with SCSS", + "_body": [ + "", + "", + "", + "", + "" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Single File Component Composition API Reactive", + "_prefix": "vbase-3-reactive", + "_description": "Base for Vue File Composition API with SCSS", + "_body": [ + "", + "", + "", + "", + "" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Single File Component Composition API with Typescript", + "_prefix": "vbase-3-ts", + "_description": "Base for Vue File Composition API - Typescript", + "_body": [ + "", + "", + "", + "", + "" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Single File Component Setup Composition API with Typescript", + "_prefix": "vbase-3-ts-setup", + "_description": "Base for Vue File Setup Composition API - Typescript", + "_body": [ + "", + "", + "", + "", + "" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Single File Component with Class based Typescript format", + "_prefix": "vbase-ts-class", + "_description": "Base for Vue File with Class based Typescript format", + "_body": [ + "", + "", + "", + "", + "" + ], + "_scope": "", + "eol": "\n" + } + ] + }, + { + "languages": {}, + "path": "/home/rob/.vscode-oss/extensions/sdras.vue-vscode-snippets-3.1.1/snippets/vue-pug.json", + "snippets": [ + { + "_name": "Vue v-for", + "_prefix": "vfor", + "_description": "vfor statement", + "_body": [ + "${1:div}(v-for=\"${2:item} in ${2:item}s\" :key=\"${2:item}.id\")", + "\t| {{ ${2:item} }}" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue v-model Directive", + "_prefix": "vmodel", + "_description": "v-model directive", + "_body": ["input(v-model=\"${1:data}\" type=\"text\")"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue v-model Number Directive", + "_prefix": "vmodel-num", + "_description": "v-model directive number input", + "_body": [ + "input(v-model.number=\"${1:numData}\" type=\"number\" step=\"1\")" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue v-on Shortcut Directive", + "_prefix": "von", + "_description": "v-on click handler with arguments", + "_body": ["@click=\"${1:handler}(${2:arg}, $event)\""], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Component with Props Binding", + "_prefix": "vel-props", + "_description": "component element with props", + "_body": ["${1:component}(:${1:propName}=\"${0}\")"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Image Source Binding", + "_prefix": "vsrc", + "_description": "image source binding", + "_body": [ + "img(:src=\"'/path/to/images/' + ${1:fileName}\" alt=\"${2:altText}\")" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Style Binding", + "_prefix": "vstyle", + "_description": "vue inline style binding", + "_body": ["${1:div}(:style=\"{ fontSize: ${2:data} + 'px' }\")"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Style Binding Object", + "_prefix": "vstyle-obj", + "_description": "vue inline style binding, objects", + "_body": [ + "${1:div}(:style=\"[${2:styleObjectA}, ${3:styleObjectB]}\")" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Class Binding", + "_prefix": "vclass", + "_description": "vue class binding", + "_body": ["${1:div}(:class=\"{ ${2:className}: ${3:data} }\")"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Class Binding Object", + "_prefix": "vclass-obj", + "_description": "vue class binding", + "_body": [ + "${1:div}(:class=\"[${2:classNameA}, ${3:classNameB}]\")" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Multiple Conditional Class Bindings", + "_prefix": "vclass-obj-mult", + "_description": "vue multiple conditional class bindings", + "_body": [ + "${1:div}(:class=\"[${2:classNameA}, {${3:classNameB} : ${4:condition}}]\")" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Transition Component with JavaScript Hooks", + "_prefix": "vanim", + "_description": "transition component js hooks", + "_body": [ + "transition(", + "\tmode=\"out-in\"", + "\t@before-enter=\"beforeEnter\"", + "\t@enter=\"enter\"", + "", + "\t@before-leave=\"beforeLeave\"", + "\t@leave=\"leave\"", + "\t:css=\"false\"", + ")" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Nuxt Routing Link", + "_prefix": "vnuxtl", + "_description": "nuxt routing link", + "_body": ["nuxt-link(to=\"/${1:page}\") ${1:page}"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Emit from Child", + "_prefix": "vemit-child", + "_description": "Vue Emit from Child Component", + "_body": ["@change=\"$emit('change', $event.target.value)\""], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Emit to Parent", + "_prefix": "vemit-parent", + "_description": "Vue Emit to Parent Component", + "_body": ["@change=\"${1:foo} = $event\""], + "_scope": "", + "eol": "\n" + } + ] + }, + { + "languages": {}, + "path": "/home/rob/.vscode-oss/extensions/sdras.vue-vscode-snippets-3.1.1/snippets/vue-template.json", + "snippets": [ + { + "_name": "Vue v-for", + "_prefix": "vfor", + "_description": "vfor statement", + "_body": [ + "<${1:div} v-for=\"${2:item} in ${2:item}s\" :key=\"${2:item}.id\">", + "\t{{ ${2:item} }}", + "" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue v-model Directive", + "_prefix": "vmodel", + "_description": "v-model directive", + "_body": [""], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue v-model Number Directive", + "_prefix": "vmodel-num", + "_description": "v-model directive number input", + "_body": [ + "" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue v-on Shortcut Directive", + "_prefix": "von", + "_description": "v-on click handler with arguments", + "_body": ["@click=\"${1:handler}(${2:arg}, $event)\""], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Component with Props Binding", + "_prefix": "vel-props", + "_description": "component element with props", + "_body": [ + "<${1:component} :${1:propName}=\"${0}\">" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Named Slot", + "_prefix": "vslot-named", + "_description": "named slot", + "_body": [ + "" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Image Source Binding", + "_prefix": "vsrc", + "_description": "image source binding", + "_body": [ + "\"${2:altText}\"/" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Style Binding", + "_prefix": "vstyle", + "_description": "vue inline style binding", + "_body": [ + "<${1:div} :style=\"{ fontSize: ${2:data} + 'px' }\">" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Style Binding Object", + "_prefix": "vstyle-obj", + "_description": "vue inline style binding, objects", + "_body": [ + "<${1:div} :style=\"[${2:styleObjectA}, ${3:styleObjectB]}\">" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Class Binding", + "_prefix": "vclass", + "_description": "vue class binding", + "_body": [ + "<${1:div} :class=\"{ ${2:className}: ${3:data} }\">" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Class Binding Object", + "_prefix": "vclass-obj", + "_description": "vue class binding", + "_body": [ + "<${1:div} :class=\"[${2:classNameA}, ${3:classNameB}]\">" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Multiple Conditional Class Bindings", + "_prefix": "vclass-obj-mult", + "_description": "vue multiple conditional class bindings", + "_body": [ + "<${1:div} :class=\"[${2:classNameA}, {${3:classNameB} : ${4:condition}}]\">" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Emit from Child", + "_prefix": "vemit-child", + "_description": "Vue Emit from Child Component", + "_body": ["@change=\"$emit('change', $event.target.value)\""], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Emit to Parent", + "_prefix": "vemit-parent", + "_description": "Vue Emit to Parent Component", + "_body": ["@change=\"${1:foo} = $event\""], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Transition Component with JavaScript Hooks", + "_prefix": "vanim", + "_description": "transition component js hooks", + "_body": [ + "", + "", + "" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Nuxt Routing Link", + "_prefix": "vnuxtl", + "_description": "nuxt routing link", + "_body": ["${1:page}"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Named Routing Link", + "_prefix": "vroutename", + "_description": "Named routing link", + "_body": [ + "${2:LinkTitle}" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Named Routing Link with Params", + "_prefix": "vroutenameparam", + "_description": "Named routing link w/ params", + "_body": [ + "${4:LinkTitle}" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Path Routing Link", + "_prefix": "vroutepath", + "_description": "Path routing link", + "_body": [ + "${2:LinkTitle}" + ], + "_scope": "", + "eol": "\n" + } + ] + }, + { + "languages": {}, + "path": "/home/rob/.vscode-oss/extensions/sdras.vue-vscode-snippets-3.1.1/snippets/vue-script.json", + "snippets": [ + { + "_name": "Vue Data", + "_prefix": "vdata", + "_description": "Vue Component Data", + "_body": [ + "data() {", + "\treturn {", + "\t\t${1:key}: ${2:value}", + "\t}", + "}," + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Methods", + "_prefix": "vmethod", + "_description": "vue method", + "_body": ["methods: {", "\t${1:name}() {", "\t\t${0}", "\t}", "},"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Computed", + "_prefix": "vcomputed", + "_description": "computed value", + "_body": [ + "computed: {", + "\t${1:name}() {", + "\t\treturn this.${2:data} ${0}", + "\t}", + "}," + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Lifecycle beforeCreate", + "_prefix": "vbeforecreate", + "_description": "beforeCreate lifecycle method", + "_body": ["beforeCreate () {", "\t${0};", "},"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Lifecycle created", + "_prefix": "vcreated", + "_description": "created lifecycle method", + "_body": ["created () {", "\t${0};", "},"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Lifecycle beforeMount", + "_prefix": "vbeforemount", + "_description": "beforeMount lifecycle method", + "_body": ["beforeMount () {", "\t${0};", "},"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Lifecycle mounted", + "_prefix": "vmounted", + "_description": "mounted lifecycle method", + "_body": ["mounted () {", "\t${0};", "},"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Lifecycle beforeUpdate", + "_prefix": "vbeforeupdate", + "_description": "beforeUpdate lifecycle method", + "_body": ["beforeUpdate () {", "\t${0};", "},"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Lifecycle updated", + "_prefix": "vupdated", + "_description": "updated lifecycle method", + "_body": ["updated () {", "\t${0};", "},"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Lifecycle beforeDestroy", + "_prefix": "vbeforedestroy", + "_description": "beforeDestroy lifecycle method", + "_body": ["beforeDestroy () {", "\t${0};", "},"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Lifecycle destroyed", + "_prefix": "vdestroyed", + "_description": "destroyed lifecycle method", + "_body": ["destroyed () {", "\t${0};", "},"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Watchers", + "_prefix": "vwatcher", + "_description": "vue watcher", + "_body": [ + "watch: {", + "\t${1:data}(${2:newValue}, ${3:oldValue}) {", + "\t\t${0}", + "\t}", + "}," + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Watchers with Options", + "_prefix": "vwatcher-options", + "_description": "vue watcher with options", + "_body": [ + "watch: {", + "\t${1:data}: {", + "\t\timmediate: ${2:true},", + "\t\tdeep: ${3:true},", + "\t\thandler(${4:newValue}, ${5:oldValue}) {", + "\t\t\t${0}", + "\t\t}", + "\t}", + "}," + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Props with Default", + "_prefix": "vprops", + "_description": "Vue Props with Default", + "_body": [ + "props: {", + "\t${1:propName}: {", + "\t\ttype: ${2:Number},", + "\t\tdefault: ${0}", + "\t},", + "}," + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Import File", + "_prefix": "vimport", + "_description": "Import one component into another", + "_body": ["import ${1:New} from '@/components/${1:New}.vue';"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Import into the Component", + "_prefix": "vcomponents", + "_description": "Import one component into another, within export statement", + "_body": ["components: {", "\t${1:New},", "},"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Import Export", + "_prefix": "vimport-export", + "_description": "import a component and include it in export default", + "_body": [ + "import ${1:Name} from '@/components/${1:Name}.vue';", + "", + "export default {", + "\tcomponents: {", + "\t\t${1:Name}", + "\t},", + "};" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Import Component Dynamically", + "_prefix": "vimport-dynamic", + "_description": "Import component that should be lazy loaded", + "_body": ["${1:New} = () => import('@/components/${1:New}.vue')"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue MapState", + "_prefix": "vmapstate", + "_description": "map getters inside a vue component", + "_body": [ + "import { mapState } from 'vuex';", + "", + "export default {", + "\tcomputed: {", + "\t\t...mapState([", + "\t\t\t${1:'nameOfState'},", + "\t\t])", + "\t},", + "};" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue MapGetters", + "_prefix": "vmapgetters", + "_description": "mapgetters inside a vue component", + "_body": [ + "import { mapGetters } from 'vuex';", + "", + "export default {", + "\tcomputed: {", + "\t\t...mapGetters([", + "\t\t\t${1:'nameOfGetter'},", + "\t\t])", + "\t},", + "};" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue MapMutations", + "_prefix": "vmapmutations", + "_description": "mapmutations inside a vue component", + "_body": [ + "import { mapMutations } from 'vuex';", + "", + "export default {", + "\tmethods: {", + "\t\t...mapMutations([", + "\t\t\t${1:'nameOfMutation'}, //also supports payload `this.nameOfMutation(amount)` ", + "\t\t])", + "\t},", + "};" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue MapActions", + "_prefix": "vmapactions", + "_description": "mapactions inside a vue component", + "_body": [ + "import { mapActions } from 'vuex';", + "", + "export default {", + "\tmethods: {", + "\t\t...mapActions([", + "\t\t\t${1:'nameOfAction'}, //also supports payload `this.nameOfAction(amount)` ", + "\t\t])", + "\t},", + "};" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Filter", + "_prefix": "vfilter", + "_description": "vue filter", + "_body": [ + "filters: {", + "\t${1:fnName}: function(${2:value}) {", + "\t\treturn ${2:value}${0};", + "\t}", + "}" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Mixin", + "_prefix": "vmixin", + "_description": "vue mixin", + "_body": [ + "const ${1:mixinName} = {", + "\tmounted() {", + "\t\tconsole.log('hello from mixin!');", + "\t},", + "};" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Use Mixin", + "_prefix": "vmixin-use", + "_description": "vue use mixin", + "_body": ["mixins: [${1:mixinName}],"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Custom Directive", + "_prefix": "vc-direct", + "_description": "vue custom directive", + "_body": [ + "Vue.directive('${1:directiveName}', {", + "\tbind(el, binding, vnode) {", + "\t\tel.style.${2:arg} = binding.value.${2:arg};", + "\t}", + "});" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Import Library", + "_prefix": "vimport-lib", + "_description": "import a library", + "_body": ["import { ${1:libName} } from '${1:libName}';"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Import GSAP", + "_prefix": "vimport-gsap", + "_description": "import gsap library", + "_body": ["import gsap from 'gsap';"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Transition Methods with JavaScript Hooks", + "_prefix": "vanimhook-js", + "_description": "transition component js hooks", + "_body": [ + "beforeEnter(el) {", + "\tconsole.log('beforeEnter');", + "},", + "enter(el, done) {", + "\tconsole.log('enter');", + "\tdone();", + "},", + "beforeLeave(el) {", + "\tconsole.log('beforeLeave');", + "},", + "leave(el, done) {", + "\tconsole.log('leave');", + "\tdone();", + "}," + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Commit Vuex Store in Methods", + "_prefix": "vcommit", + "_description": "commit to vuex store in methods for mutation", + "_body": [ + "${1:mutationName}() {", + "\tthis.\\$store.commit('${1:mutationName}', ${2:payload});", + "}" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Dispatch Vuex Store in Methods", + "_prefix": "vdispatch", + "_description": "dispatch to vuex store in methods for action", + "_body": [ + "${1:actionName}() {", + "\tthis.\\$store.dispatch('${1:actionName}', ${2:payload});", + "}" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Unit Test", + "_prefix": "vtest", + "_description": "unit test component", + "_body": [ + "import Vue from 'vue';", + "import ${1:HelloWorld} from './components/${1:HelloWorld}';", + "", + "describe('${1:HelloWorld}.vue', () => {", + "\tit('${2:should render correct contents}', () => {", + "\t\tconst Constructor = Vue.extend(${1:HelloWorld});", + "\t\tconst vm = new Constructor().$mount();", + "\t\texpect(vm.$el.querySelector('.hello h1').textContent)", + "\t\t\t.to.equal(${3:'Welcome to Your Vue.js App'});", + "\t});", + "});" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue.config.js Import", + "_prefix": "vconfig", + "_description": "vue.config.js", + "_body": [ + "module.exports = {", + "\tcss: {", + "\t\tloaderOptions: {", + "\t\t\t${1:sass}: {", + "\t\t\t\tdata: `${2:@import '@/styles/_variables.scss';}`", + "\t\t\t}", + "\t\t}", + "\t}", + "}" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Composition API - Reactive", + "_prefix": "v3reactive", + "_description": "Vue Composition api - reactive", + "_body": [ + "const ${1:name} = reactive({", + "\t${2:count}: ${3:0}", + "})" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Composition API - Computed", + "_prefix": "v3computed", + "_description": "Vue Composition api - computed", + "_body": [ + "const ${1:name} = computed(() => {", + "\treturn ${2}", + "})" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Composition API - watch - single source", + "_prefix": "v3watch", + "_description": "Vue Composition api - watcher single source", + "_body": [ + "watch(() => ${1:foo}, (newValue, oldValue) => {", + "\t${2}", + "})" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Composition API - watch - array", + "_prefix": "v3watch-array", + "_description": "Vue Composition api - watch as array", + "_body": [ + "watch([${1:foo}, ${2:bar}], ([new${1}, new${2}], [prev${1}, prev${2}]) => {", + "\t${3}", + "})" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Composition API - watchEffect", + "_prefix": "v3watcheffect", + "_description": "Vue Composition api - watchEffect", + "_body": ["watchEffect(() => {", "\t${1}", "})"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Composition API - Vue ref", + "_prefix": "v3ref", + "_description": "Vue Ref", + "_body": ["const ${1:name} = ref(${2:initialValue})"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Lifecycle Hooks - onMounted", + "_prefix": "v3onmounted", + "_description": "Vue Mounted Lifecycle hook", + "_body": ["onMounted(() => {${1}})"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Lifecycle Hooks - onBeforeMount", + "_prefix": "v3onbeforemount", + "_description": "Vue onBeforeMount Lifecycle hook", + "_body": ["onBeforeMount(() => {${1}})"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Lifecycle Hooks - onBeforeUpdate", + "_prefix": "v3onbeforeupdate", + "_description": "Vue onBeforeUpdate Lifecycle hook", + "_body": ["onBeforeUpdate(() => {${1}})"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Lifecycle Hooks - onUpdated", + "_prefix": "v3onupdated", + "_description": "Vue onUpdated Lifecycle hook", + "_body": ["onUpdated(() => {${1}})"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Lifecycle Hooks - onErrorCaptured", + "_prefix": "v3onerrorcaptured", + "_description": "Vue onErrorCaptured Lifecycle hook", + "_body": ["onErrorCaptured(() => {${1}})"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Lifecycle Hooks - onUnmounted", + "_prefix": "v3onunmounted", + "_description": "(destroyed) Vue onUnmounted Lifecycle hook", + "_body": ["onUnmounted(() => {${1}})"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Lifecycle Hooks - onBeforeUnmount", + "_prefix": "v3onbeforeunmount", + "_description": "(beforeDestroy) Vue onBeforeUnmount Lifecycle hook", + "_body": ["onBeforeUnmount(() => {${1}})"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Plugin import", + "_prefix": "vplugin", + "_description": "Import a plugin to main.js or plugins file", + "_body": [ + "import Vue from 'vue'", + "import ${1:VueCompositionApi} from '${2:@vue/composition-api}'", + "", + "Vue.use(${1:VueCompositionApi})" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Composition API Reactive Script", + "_prefix": "v3reactive-setup", + "_description": "Vue Composition API Script with Reactive", + "_body": [ + "import { reactive, toRefs } from 'vue'", + "", + "export default {", + "\tsetup () {", + "\t\tconst state = reactive({", + "\t\t\t${0:count}: ${1:0},", + "\t\t})", + "\t", + "\t\treturn {", + "\t\t\t...toRefs(state),", + "\t\t}", + "\t}", + "}" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Use Composition API within Options API", + "_prefix": "v3useinoptions", + "_description": "Use Composition API within Options API", + "_body": [ + "import { ${0:component} } from '@/composables/${0:component}.js'", + "", + "export default {", + "\tsetup () {", + "\t\tconst { ${1:name} } = ${0:component}()", + "\t", + "\t\treturn {", + "\t\t\t${1:name}", + "\t\t}", + "\t}", + "}" + ], + "_scope": "", + "eol": "\n" + } + ] + }, + { + "languages": {}, + "path": "/home/rob/.vscode-oss/extensions/sdras.vue-vscode-snippets-3.1.1/snippets/vue-script-vuex.json", + "snippets": [ + { + "_name": "Vuex Store", + "_prefix": "vstore", + "_description": "Base for Vuex store", + "_body": [ + "import Vue from 'vue';", + "import Vuex from 'vuex';", + "", + "Vue.use(Vuex);", + "", + "export const store = new Vuex.Store({", + "\tstate: {", + "\t\t${1:key}: ${2:value}", + "\t}", + "});" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vuex Getters", + "_prefix": "vgetter", + "_description": "vuex getter", + "_body": [ + "getters: {", + "\t${1:value}: state => {", + "\t\treturn state.${1:value};", + "\t}", + "}" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vuex Mutation", + "_prefix": "vmutation", + "_description": "vuex mutation", + "_body": [ + "mutations: {", + "\t${1:updateValue}(state, ${3:payload}) {", + "\t\tstate.${2:value} = ${3:payload};", + "\t}", + "}" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vuex Action", + "_prefix": "vaction", + "_description": "vuex action", + "_body": [ + "actions: {", + "\t${1:updateValue}({commit}, ${2:payload}) {", + "\t\tcommit('${1:updateValue}', ${2:payload});", + "\t}", + "}" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Import Vuex Store", + "_prefix": "vstore-import", + "_description": "import vuex store into main.js", + "_body": ["import { store } from './store/index';"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vuex Module", + "_prefix": "vmodule", + "_description": "vuex module", + "_body": [ + "export default {", + "\tstate: {", + "\t\tvalue: 'my value'", + "\t},", + "\tgetters: {", + "\t\tvalue: state => {", + "\t\t\treturn state.value;", + "\t\t}", + "\t},", + "\tmutations: {", + "\t\tupdateValue(state, payload) {", + "\t\t\tstate.value = payload;", + "\t\t}", + "\t},", + "\tactions: {", + "\t\tupdateValue({commit}, payload) {", + "\t\t\tcommit('updateValue', payload);", + "\t\t}", + "\t}", + "};" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vuex Store 2", + "_prefix": "vstore2", + "_description": "vuex store 2", + "_body": [ + "export const state = () => ({", + "\tvalue: 'myvalue'", + "})", + "", + "export const getters = {", + "\tgetterValue: state => {", + "\t\treturn state.value", + "\t}", + "}", + "", + "export const mutations = {", + "\tupdateValue: (state, payload) => {", + "\t\tstate.value = payload", + "\t}", + "}", + "", + "export const actions = {", + "\tupdateActionValue({ commit }) {", + "\t\tcommit('updateValue', payload)", + "\t}", + "}" + ], + "_scope": "", + "eol": "\n" + } + ] + }, + { + "languages": {}, + "path": "/home/rob/.vscode-oss/extensions/sdras.vue-vscode-snippets-3.1.1/snippets/vue-script-router.json", + "snippets": [ + { + "_name": "Vue Router", + "_prefix": "vrouter", + "_description": "Base for Vue Router", + "_body": [ + "import Vue from 'vue';", + "import VueRouter from 'vue-router';", + "", + "Vue.use(VueRouter);", + "", + "export const router = new VueRouter({", + "\tbase: '/',", + "\tmode: 'history',", + "\troutes: [", + "\t\t{ path: '/path', component: component }", + "\t]", + "});" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Router scrollBehavior", + "_prefix": "vscrollbehavior", + "_description": "Vue Router scrollBehavior", + "_body": [ + "scrollBehavior(to, from, savedPosition) {", + "\tif(savedPosition) {", + "\t\treturn savedPosition;", + "\t} else {", + "\t\treturn { x: 0, y: 0 };", + "\t}", + "}," + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Router beforeEach", + "_prefix": "vbeforeeach", + "_description": "Vue Router global guards beforeEach", + "_body": [ + "router.beforeEach((to, from, next) => {", + "\t${1:next();}", + "});" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Router beforeResolve", + "_prefix": "vbeforeresolve", + "_description": "Vue Router global guards beforeResolve", + "_body": [ + "router.beforeResolve((to, from, next) => {", + "\t${1:next();}", + "});" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Router afterEach", + "_prefix": "vaftereach", + "_description": "Vue Router global guards afterEach", + "_body": ["router.afterEach((to, from) => {", "\t", "});"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Router beforeEnter", + "_prefix": "vbeforeenter", + "_description": "Vue Router per-route guard beforeEnter", + "_body": ["beforeEnter(to, from, next) {", "\t${1:next();}", "},"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Router beforeRouteEnter", + "_prefix": "vbeforerouteenter", + "_description": "Vue Router component guards beforeRouteEnter", + "_body": [ + "beforeRouteEnter(to, from, next) {", + "\tnext(vm => {${1:}});", + "}," + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Router beforeRouteUpdate", + "_prefix": "vbeforerouteupdate", + "_description": "Vue Router component guards beforeRouteUpdate", + "_body": [ + "beforeRouteUpdate(to, from, next) {", + "\t${1:next();}", + "}," + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Router beforeRouteLeave", + "_prefix": "vbeforerouteleave", + "_description": "Vue Router component guards beforeRouteLeave", + "_body": [ + "beforeRouteLeave(to, from, next) {", + "\t${1:next();}", + "}," + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Vue Router Route", + "_prefix": "vroute-named", + "_description": "Vue Router route with per route code-splitting", + "_body": [ + "{", + "\tpath: '${1:pathName}',", + "\tname: '${2:routeName}',", + "\tcomponent: () => import('./${3:pathToComponent}'),", + "}," + ], + "_scope": "", + "eol": "\n" + } + ] + }, + { + "languages": {}, + "path": "/home/rob/.vscode-oss/extensions/sdras.vue-vscode-snippets-3.1.1/snippets/nuxt-config.json", + "snippets": [ + { + "_name": "Nuxt Font", + "_prefix": "nfont", + "_description": "link to include fonts in a nuxt project, in nuxt-config", + "_body": [ + "{ rel: 'stylesheet', href: '${1:https://fonts.googleapis.com/css?family=Montserrat:600|Rufina:700}' }" + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Nuxt Use CSS File", + "_prefix": "ncss", + "_description": "link to css assets such as normalize", + "_body": ["css: ['assets/${1:normalize.css}'],"], + "_scope": "", + "eol": "\n" + } + ] + }, + { + "languages": {}, + "path": "/home/rob/.vscode-oss/extensions/sdras.vue-vscode-snippets-3.1.1/snippets/nuxt-script.json", + "snippets": [ + { + "_name": "Nuxt Async", + "_prefix": "nasyncdataaxios", + "_description": "Nuxt asyncData with Axios module", + "_body": [ + "async asyncData ({ ${1:$axios}, { ${2:params} }) {", + "\tconst data = await $axios.$get(`${3:endpoint/${params.slug}}`)", + "\treturn { data }", + "}," + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Nuxt Fetch", + "_prefix": "nfetch", + "_description": "Nuxt Fetch", + "_body": [ + "async fetch ({ store, ${1:params} }) {", + "\tlet { data } = await fetch('${2:endpoint}').then(res => res.json())", + "\tstore.commit('${3:MUTATION_TYPE}', data)", + "}," + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Nuxt Fetch with Axios", + "_prefix": "nfetchaxios", + "_description": "Nuxt Fetch with Axios module", + "_body": [ + "async fetch () {", + "\tlet this.data = await this.$axios.$get('${1:endpoint/${this.$route.params.slug}}')", + "}," + ], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Nuxt Route Params", + "_prefix": "nparam", + "_description": "Nuxt Route Params", + "_body": ["this.$route.params.${1:id}"], + "_scope": "", + "eol": "\n" + }, + { + "_name": "Nuxt Head", + "_prefix": "nhead", + "_description": "Nuxt Head", + "_body": [ + "head () {", + "\treturn {", + "\t\ttitle: ${1:'Page Title'},", + "\t\tmeta: [", + "\t\t\t// hid is used as unique identifier. Do not use `vmid` for it as it will not work", + "\t\t\t{ hid: 'description', name: 'description', content: ${2:'My custom description'} }", + "\t\t]", + "\t}", + "}," + ], + "_scope": "", + "eol": "\n" + } + ] + } + ] + } +] diff --git a/test/suite/extension.test.js b/test/suite/extension.test.js deleted file mode 100644 index 27f9d15..0000000 --- a/test/suite/extension.test.js +++ /dev/null @@ -1,34 +0,0 @@ -// eslint-disable-next-line import/no-unresolved, node/no-missing-require -const vscode = require("vscode"); -const assert = require("assert"); - -describe("Extension", () => { - const extensionID = "robole.snippets-ranger"; - const extensionShortName = "snippets-ranger"; - - let extension; - - before(() => { - extension = vscode.extensions.getExtension(extensionID); - }); - - it("All package.json commands should be registered in extension", (done) => { - const packageCommands = extension.packageJSON.contributes.commands.map( - (c) => c.command - ); - - // get all extension commands excluding internal commands. - vscode.commands.getCommands(true).then((allCommands) => { - const activeCommands = allCommands.filter((c) => - c.startsWith(`${extensionShortName}.`) - ); - - activeCommands.forEach((command) => { - const result = packageCommands.some((c) => c === command); - assert.ok(result); - }); - - done(); - }); - }); -}); diff --git a/test/suite/formatter.test.js b/test/suite/formatter.test.js deleted file mode 100644 index e2ef4e8..0000000 --- a/test/suite/formatter.test.js +++ /dev/null @@ -1,100 +0,0 @@ -const assert = require("assert"); -const formatter = require("../../src/formatter"); - -describe("Formatter", () => { - describe("convertToArray()", () => { - it("should create an array from a single-line string", () => { - let array = formatter.convertToArray("some text"); - assert.strictEqual(array[0], "some text"); - }); - - it("should create an array from a multi-line string", () => { - let array = formatter.convertToArray("line 1\nline 2"); - assert.strictEqual(array.length, 2); - assert.strictEqual(array[1], "line 2"); - }); - }); - - describe("formatTitle()", () => { - it("should capitilize most languages", () => { - let js = formatter.formatTitle("javascript"); - let python = formatter.formatTitle("python"); - - assert.strictEqual(js, "Javascript"); - assert.strictEqual(python, "Python"); - }); - - it("should uppercase some languages", () => { - let html = formatter.formatTitle("html"); - let css = formatter.formatTitle("css"); - - assert.strictEqual(html, "HTML"); - assert.strictEqual(css, "CSS"); - }); - }); - - describe("capitalize()", () => { - it("should capitilize the first word", () => { - let word = formatter.formatTitle("word1 word2"); - - assert.strictEqual(word, "Word1 word2"); - }); - }); - - describe("escapeHtml()", () => { - it("should replace html element with a HTML-safe equivalent", () => { - let text1 = formatter.escapeHtml(`This is the tag.`); - - assert.strictEqual(text1, "This is the <html> tag."); - }); - - it("should replace single quotes, double quotes, and ampersands with a HTML-safe equivalent", () => { - let text2 = formatter.escapeHtml(`No '"& allowed.`); - - assert.strictEqual(text2, "No '"& allowed."); - }); - - it("should replace a tab with a HTML-safe equivalent", () => { - let text3 = formatter.escapeHtml(`\t let x = 1;`); - - assert.strictEqual(text3, "  let x = 1;"); - }); - - it("should replace line breaks with a HTML-safe equivalent", () => { - let text1 = formatter.escapeHtml(`Line 1.\r\nLine 2.`); - let text2 = formatter.escapeHtml(`Line 1.\nLine 2.`); - - assert.strictEqual(text1, "Line 1.
    Line 2."); - assert.strictEqual(text2, "Line 1.
    Line 2."); - }); - - it("should replace an escaped backslash with a HTML-safe equivalent", () => { - let text = formatter.escapeHtml("`\\$num is a variable`;"); - assert.strictEqual(text, "`\\$num is a variable`;"); - }); - }); - - describe("slugify()", () =>{ - it("should slugify in a GitHub style by creating a trimmed, lowercase, hypenated version of the string", () => { - assert.equal( - formatter.slugify(" Robole Github com "), - "robole-github-com" - ); - }); - - it("should slugify by removing characters that are not: a letter, space or hypen", () => { - assert.equal(formatter.slugify("robole 🙏 com"), "robole--com"); - assert.equal( - formatter.slugify("Uniform Resource Locator (URL)"), - "uniform-resource-locator-url" - ); - assert.equal(formatter.slugify("[re] [] [f])"), "re--f"); - assert.equal( - formatter.slugify("[robole.github.io"), - "robolegithubio" - ); - assert.equal(formatter.slugify("robole 🙏 com-"), "robole--com-"); - assert.equal(formatter.slugify("ha 🐇-👎"), "ha--"); - }); - }); -}); diff --git a/test/suite/helper/format.test.js b/test/suite/helper/format.test.js new file mode 100644 index 0000000..7527474 --- /dev/null +++ b/test/suite/helper/format.test.js @@ -0,0 +1,102 @@ +const assert = require("assert"); +const format = require("../../../src/helper/format"); + +describe("format.js", () => { + describe("convertToArray()", () => { + it("should create an array from a single-line string", () => { + let array = format.convertToArray("some text"); + assert.strictEqual(array[0], "some text"); + }); + + it("should create an array from a multi-line string on windows", () => { + let array = format.convertToArray("line 1\r\nline 2"); + assert.strictEqual(array.length, 2); + assert.strictEqual(array[1], "line 2"); + }); + + it("should create an array from a multi-line string on *nix", () => { + let array = format.convertToArray("line 1\nline 2"); + assert.strictEqual(array.length, 2); + assert.strictEqual(array[1], "line 2"); + }); + }); + + describe("capitalize()", () => { + it("should capitilize the first word", () => { + let word = format.capitalize("word1 word2"); + + assert.strictEqual(word, "Word1 word2"); + }); + }); + + describe("escapeHtml()", () => { + it("should replace html element with a HTML-safe equivalent", () => { + let text1 = format.escapeHtml(`This is the tag.`); + + assert.strictEqual(text1, "This is the <html> tag."); + }); + + it("should replace single quotes, double quotes, and ampersands with a HTML-safe equivalent", () => { + let text2 = format.escapeHtml(`No '"& allowed.`); + + assert.strictEqual(text2, "No '"& allowed."); + }); + + it("should replace a tab with a HTML-safe equivalent", () => { + let text3 = format.escapeHtml(`\t let x = 1;`); + + assert.strictEqual(text3, "  let x = 1;"); + }); + + it("should replace line breaks with a HTML-safe equivalent", () => { + let text1 = format.escapeHtml(`Line 1.\r\nLine 2.`); + let text2 = format.escapeHtml(`Line 1.\nLine 2.`); + + assert.strictEqual(text1, "Line 1.
    Line 2."); + assert.strictEqual(text2, "Line 1.
    Line 2."); + }); + + it("should replace an escaped backslash with a HTML-safe equivalent", () => { + let text = format.escapeHtml("`\\$num is a variable`;"); + assert.strictEqual(text, "`\\$num is a variable`;"); + }); + }); + + describe("slugify()", () => { + it("should slugify in a GitHub style by creating a trimmed, lowercase, hypenated version of the string", () => { + assert.equal(format.slugify(" Robole Github com "), "robole-github-com"); + }); + + it("should slugify by removing characters that are not: a letter, space or hypen", () => { + assert.equal(format.slugify("robole 🙏 com"), "robole--com"); + assert.equal( + format.slugify("Uniform Resource Locator (URL)"), + "uniform-resource-locator-url" + ); + assert.equal(format.slugify("[re] [] [f])"), "re--f"); + assert.equal(format.slugify("[robole.github.io"), "robolegithubio"); + assert.equal(format.slugify("robole 🙏 com-"), "robole--com-"); + assert.equal(format.slugify("ha 🐇-👎"), "ha--"); + }); + }); + + describe("escapeBody()", () => { + it("should replace html elements with a HTML-safe equivalent for a string", () => { + let body = format.escapeBody(`This is the tag.`); + + assert.strictEqual(body, "This is the <html> tag."); + }); + + it("should replace html elements with a HTML-safe equivalent for an array", () => { + let text1 = format.escapeBody([ + `This is the tag.`, + `\t let x = 1;`, + ]); + + assert.strictEqual( + text1, + "This is the <html> tag.
      let x = 1;
    " + ); + }); + }); +}); diff --git a/test/suite/index.js b/test/suite/index.js index 4ccec89..c37fb1b 100644 --- a/test/suite/index.js +++ b/test/suite/index.js @@ -1,44 +1,43 @@ -const path = require("path"); -const Mocha = require("mocha"); -const glob = require("glob"); - -function run() { - // Create the mocha test - const mocha = new Mocha({ - ui: "bdd", - color: true, - timeout: 2000, - }); - mocha.set; - - const testsRoot = path.resolve(__dirname, ".."); - - return new Promise((c, e) => { - glob("**/**.test.js", { cwd: testsRoot }, (err, files) => { - if (err) { - return e(err); - } - - // Add files to the test suite - files.forEach((f) => mocha.addFile(path.resolve(testsRoot, f))); - - try { - // Run the mocha test - mocha.run((failures) => { - if (failures > 0) { - e(new Error(`${failures} tests failed.`)); - } else { - c(); - } - }); - } catch (err) { - console.error(err); - e(err); - } - }); - }); -} - -module.exports = { - run, -}; +const path = require("path"); +const Mocha = require("mocha"); +const glob = require("glob"); + +function run() { + // Create the mocha test + const mocha = new Mocha({ + ui: "bdd", + color: true, + timeout: 4000, + }); + + const testsRoot = path.resolve(__dirname, ".."); + + return new Promise((c, e) => { + glob("**/**.test.js", { cwd: testsRoot }, (err, files) => { + if (err) { + return e(err); + } + + // Add files to the test suite + files.forEach((f) => mocha.addFile(path.resolve(testsRoot, f))); + + try { + // Run the mocha test + mocha.run((failures) => { + if (failures > 0) { + e(new Error(`${failures} tests failed.`)); + } else { + c(); + } + }); + } catch (error) { + console.error(error); + e(error); + } + }); + }); +} + +module.exports = { + run, +}; diff --git a/test/suite/main.test.js b/test/suite/main.test.js new file mode 100644 index 0000000..8878954 --- /dev/null +++ b/test/suite/main.test.js @@ -0,0 +1,36 @@ +// eslint-disable-next-line import/no-unresolved, node/no-missing-require +const vscode = require("vscode"); +const assert = require("assert"); + +describe("extension.js", () => { + describe("Extension", () => { + const extensionID = "robole.snippets-ranger"; + const extensionShortName = "snippets-ranger"; + + let extension; + + before(() => { + extension = vscode.extensions.getExtension(extensionID); + }); + + it("All package.json commands should be registered in extension", (done) => { + const packageCommands = extension.packageJSON.contributes.commands.map( + (c) => c.command + ); + + // get all extension commands excluding internal commands. + vscode.commands.getCommands(true).then((allCommands) => { + const activeCommands = allCommands.filter((c) => + c.startsWith(`${extensionShortName}.`) + ); + + activeCommands.forEach((command) => { + const result = packageCommands.some((c) => c === command); + assert.ok(result); + }); + + done(); + }); + }); + }); +}); diff --git a/test/suite/model/snippet-file.test.js b/test/suite/model/snippet-file.test.js new file mode 100644 index 0000000..ea8cf3d --- /dev/null +++ b/test/suite/model/snippet-file.test.js @@ -0,0 +1,78 @@ +const assert = require("assert"); +const SnippetsFile = require("../../../src/model/snippets-file"); + +describe("snippets-file.js", () => { + describe("SnippetsFile", () => { + it("should create a Snippets File object with values supplied for: path and snippets", () => { + let snippet = { + name: "Region Start", + prefix: "#region", + body: ["//#region"], + description: "Folding Region Start", + scope: "", + }; + let file1 = new SnippetsFile("/somepath/java.json", [snippet]); + let file2 = new SnippetsFile("/somepath/typescript.json", []); + + assert.strictEqual(file1.path, "/somepath/java.json"); + assert.strictEqual(file1.snippets[0], snippet); + assert.strictEqual(file2.path, "/somepath/typescript.json"); + }); + + it("should create a Snippets File object with a title that is the filename without the extension", () => { + let file = new SnippetsFile("/somepath/java.json", "user", []); + + assert.strictEqual(file.getTitle(), "java"); + }); + + it("should state if any of the snippets have the `scope` field populated", () => { + let snippet = { + name: "Region Start", + prefix: "#region", + body: ["//#region"], + description: "Folding Region Start", + scope: "java", + }; + + let file = new SnippetsFile("/somepath/java.json", [snippet]); + assert.equal(file.isScoped(), true); + }); + + it(`should be able to associate a language with a Snippet File without duplication`, () => { + let snippet = { + name: "Region Start", + prefix: "#region", + body: ["//#region"], + description: "Folding Region Start", + scope: "java", + }; + + let file = new SnippetsFile("/somepath/java.json", [snippet]); + file.addLanguage("java"); + file.addLanguage("kotlin"); + file.addLanguage("java"); + assert.equal(file.getLanguages().length, 2); + assert.equal(file.getLanguages()[0], "java"); + assert.equal(file.getLanguages()[1], "kotlin"); + }); + + it(`should be able to remove association of a language with a Snippet File`, () => { + let snippet = { + name: "Region Start", + prefix: "#region", + body: ["//#region"], + description: "Folding Region Start", + scope: "java", + }; + + let file = new SnippetsFile("/somepath/java.json", [snippet]); + file.addLanguage("java"); + file.addLanguage("kotlin"); + + assert.equal(file.getLanguages().length, 2); + file.removeLanguage("java"); + assert.equal(file.getLanguages().length, 1); + assert.equal(file.getLanguages()[0], "kotlin"); + }); + }); +}); diff --git a/test/suite/model/snippet.test.js b/test/suite/model/snippet.test.js new file mode 100644 index 0000000..34d219c --- /dev/null +++ b/test/suite/model/snippet.test.js @@ -0,0 +1,55 @@ +/* eslint-disable no-template-curly-in-string */ +const assert = require("assert"); +const Snippet = require("../../../src/model/snippet"); +const util = require("../../../src/helper/util"); + +describe("snippets.js", () => { + describe("Snippet", () => { + it("should create an empty object if no arguments given to constructor", () => { + let mySnippet = new Snippet(); + assert.strictEqual(mySnippet.name, "", "name is not empty"); + assert.strictEqual(mySnippet.description, "", "description is not empty"); + assert.strictEqual( + Array.isArray(mySnippet.prefix), + true, + "prefix is not an array" + ); + assert.strictEqual( + Array.isArray(mySnippet.body), + true, + "body is not an array" + ); + }); + + it("should allow double quotes in fields", () => { + let mySnippet = new Snippet( + `my "name"`, + `my "prefix"`, + `my "body"`, + `my "description"` + ); + assert.strictEqual(mySnippet.name, `my "name"`); + assert.strictEqual(mySnippet.description, `my "description"`); + assert.strictEqual(mySnippet.prefix[0], `my "prefix"`); + assert.strictEqual(mySnippet.body[0], `my "body"`); + }); + + it("should format the `scope` field to be a sorted list of languages with equal whitespace", () => { + let snippet = new Snippet( + "stylelint disable next line", + "stylelint disable next line", + ["/* stylelint-disable-next-line ${1:rule} */$0"], + "Disable Stylelint on the next line. If no rule is specified, then all rules will be disabled.", + `xsl,html,css,less, javascript, javascriptreact, markdown, source.markdown.math, + postcss, sass, scss, source.css.styled, styled-css, sugarss, svelte, typescript, + typescriptreact, vue, vue-html, vue-postcss, xml, ` + ); + + let expectedResult = `css, html, javascript, javascriptreact, less, markdown, postcss, sass, scss, `; + expectedResult += `source.css.styled, source.markdown.math, styled-css, sugarss, svelte, typescript, `; + expectedResult += `typescriptreact, vue, vue-html, vue-postcss, xml, xsl`; + + assert.strictEqual(snippet.scope, expectedResult); + }); + }); +}); diff --git a/test/suite/snippet.test.js b/test/suite/snippet.test.js deleted file mode 100644 index 46475ba..0000000 --- a/test/suite/snippet.test.js +++ /dev/null @@ -1,45 +0,0 @@ -const assert = require("assert"); -const Snippet = require("../../src/model/snippet"); - -describe("Snippet", () => { - it("should create an empty object if no arguments given to constructor", () => { - let mySnippet = new Snippet(); - assert.strictEqual(mySnippet.name, ""); - assert.strictEqual(mySnippet.description, ""); - assert.strictEqual(mySnippet.prefix, ""); - assert.strictEqual(typeof mySnippet.body === "object", true); // it should be an array - }); - - it("should allow double quotes in fields", () => { - let mySnippet = new Snippet( - `my "name"`, - `my "prefix"`, - `my "body"`, - `my "description"` - ); - assert.strictEqual(mySnippet.name, 'my "name"'); - assert.strictEqual(mySnippet.description, 'my "description"'); - assert.strictEqual(mySnippet.prefix, 'my "prefix"'); - assert.strictEqual(mySnippet.body[0], 'my "body"'); - }); - - it("should produce a string of the object", () => { - let mySnippet = new Snippet( - `map js`, - `map`, - ['console.log("err");', 'alert("hello");'], - "blah", - "javascript, typescript" - ); - - let eol = "\n"; - - if (process.platform === "win32") { - eol = "\r\n"; - } - - let expectedResult = `${eol}"map js" : {${eol}\t"prefix": "map",${eol}\t"body": ["console.log(\\"err\\");","alert(\\"hello\\");"],${eol}\t"description": "blah"${eol}\t"scope": "javascript, typescript"${eol}}`; - - assert.strictEqual(mySnippet.toString(), expectedResult); - }); -}); diff --git a/test/suite/view/category-section.test.js b/test/suite/view/category-section.test.js new file mode 100644 index 0000000..257c17c --- /dev/null +++ b/test/suite/view/category-section.test.js @@ -0,0 +1,57 @@ +const assert = require("assert"); +const SnippetsFile = require("../../../src/model/snippets-file"); +const { createCategorySection } = require("../../../src/view/category-section"); + +describe("category-section.js", () => { + describe("createCategorySection()", () => { + it("should create a section with a heading", () => { + let snippets = []; + snippets[0] = { + name: "Region Start", + prefix: "#region", + body: ["//#region"], + description: "Folding Region Start", + scope: "", + }; + + let snippetsFile = new SnippetsFile( + "/somepath/java.code-snippets", + snippets + ); + + let section = createCategorySection([snippetsFile], "user"); + let expected = `

    User Snippets

    `; + + assert.strictEqual(section.startsWith(expected), true); + }); + + it("should create a subsection for each snippets file", () => { + let snippets = []; + snippets[0] = { + name: "Region Start", + prefix: "#region", + body: ["//#region"], + description: "Folding Region Start", + scope: "", + }; + + let snippetsFile = new SnippetsFile( + "/somepath/global-snippets.code-snippets", + snippets + ); + + let section = createCategorySection([snippetsFile], "user"); + + let expected = `

    global-snippets.code-snippets

    `; + + assert.strictEqual(section.includes(expected), true); + }); + + it("should create a section that states there are no snippets when there are no snippets", () => { + let section = createCategorySection([], "user"); + let expected = `

    Oucho Gaucho!`; + + assert.strictEqual(section.includes(expected), true); + }); + }); +}); diff --git a/test/suite/view/file-section.test.js b/test/suite/view/file-section.test.js new file mode 100644 index 0000000..409808f --- /dev/null +++ b/test/suite/view/file-section.test.js @@ -0,0 +1,66 @@ +const assert = require("assert"); +const SnippetsFile = require("../../../src/model/snippets-file"); +const { createFileSection } = require("../../../src/view/file-section"); + +describe("file-section.js", () => { + describe("createFileSection()", () => { + it("should create a section with a heading and a 'view source' button", () => { + let snippets = []; + snippets[0] = { + name: "Region Start", + prefix: "#region", + body: ["//#region"], + description: "Folding Region Start", + scope: "", + }; + + let snippetsFile = new SnippetsFile( + "/somepath/java.code-snippets", + snippets + ); + + let section = createFileSection(snippetsFile); + + let expected = `

    java.code-snippets

    `; + expected += ``; + + assert.strictEqual(section.includes(expected), true); + }); + + it("should create a section with a snippets table when there are snippets", () => { + let snippets = []; + snippets[0] = { + name: "Region Start", + prefix: "#region", + body: ["//#region"], + description: "Folding Region Start", + scope: "", + }; + + let snippetsFile = new SnippetsFile( + "/somepath/java.code-snippets", + snippets + ); + + let section = createFileSection(snippetsFile, "app"); + + let expected = ``; + + assert.strictEqual(section.includes(expected), true); + }); + + it("should create a section that states there are no snippets when there are no snippets", () => { + let snippets = []; + let snippetsFile = new SnippetsFile( + "/somepath/java.code-snippets", + snippets + ); + + let section = createFileSection(snippetsFile); + let expected = `

    No snippets`; + + assert.strictEqual(section.includes(expected), true); + }); + }); +}); diff --git a/test/suite/view/snippets-table.test.js b/test/suite/view/snippets-table.test.js new file mode 100644 index 0000000..4f0bd8d --- /dev/null +++ b/test/suite/view/snippets-table.test.js @@ -0,0 +1,72 @@ +const assert = require("assert"); +const SnippetsFile = require("../../../src/model/snippets-file"); +const { createSnippetsTable } = require("../../../src/view/snippets-table"); + +describe("snippets-table.js", () => { + describe("createSnippetsTable()", () => { + let editIcon = ``; + let deleteIcon = ``; + + it("should create a table from a snippets file", () => { + let snippets = []; + snippets[0] = { + name: "Region Start", + prefix: "#region", + body: ["//#region"], + description: "Folding Region Start", + scope: "", + }; + + let snippetsFile = new SnippetsFile( + "/somepath/java.code-snippets", + snippets + ); + + let table = createSnippetsTable(snippetsFile); + + let expected = `

    `; + expected += ``; + expected += ``; + expected += ``; + expected += ``; + expected += `
    PrefixNameDescriptionBodyAction
    #regionRegion StartFolding Region Start//#region
    `; + + assert.strictEqual(table, expected); + }); + + it("should create an empty table if there is are no snippets provided", () => { + let snippetsFile = new SnippetsFile("/somepath/java.json", []); + + let table = createSnippetsTable(snippetsFile); + + let expected = ``; + expected += ``; + expected += `
    PrefixNameDescriptionBodyAction
    `; + + assert.strictEqual(table, expected); + }); + + it("should create a table with the 'scope' column when a snippet has a populated `scope` field", () => { + let snippet = { + name: "Region Start", + prefix: "#region", + body: ["//#region"], + description: "Folding Region Start", + scope: "java", + }; + + let snippetsFile = new SnippetsFile("/somepath/a.code-snippets", [ + snippet, + ]); + + let table = createSnippetsTable(snippetsFile); + + let expected = ``; + expected += ``; + + assert.strictEqual(table.startsWith(expected), true); + }); + }); +}); diff --git a/test/suite/view/table-of-contents.test.js b/test/suite/view/table-of-contents.test.js new file mode 100644 index 0000000..d62e668 --- /dev/null +++ b/test/suite/view/table-of-contents.test.js @@ -0,0 +1,60 @@ +const assert = require("assert"); +const { + createTableOfContents, +} = require("../../../src/view/table-of-contents"); +const SnippetsFile = require("../../../src/model/snippets-file"); +const Extension = require("../../../src/model/extension"); + +describe("table-of-contents.js", () => { + describe("createTableOfContents()", () => { + it("should create an empty table if an empty outline is provided", () => { + let toc = createTableOfContents(); // OR createTableOfContents([], [], [], []); + + assert.strictEqual(toc, ""); + }); + + it("should create a table with an entry for a collection of snippets files", () => { + let snippetsFile1 = new SnippetsFile("/somepath/a.code-snippets", []); + let snippetsFile2 = new SnippetsFile("/somepath/b.code-snippets", []); + + let toc = createTableOfContents( + [snippetsFile1, snippetsFile2], + [], + [], + [] + ); + + let expectedOutput = `

    Table of Contents

      `; + expectedOutput += `
    • Project Snippets
        `; + expectedOutput += `
      • a
      • `; + expectedOutput += `
      • b
      • `; + expectedOutput += `
    • `; + expectedOutput += `
    `; + + assert.strictEqual(toc, expectedOutput); + }); + + it("should create a table with an entry for an extension and its snippets files", () => { + let snippetsFile1 = new SnippetsFile("/somepath/a.code-snippets", []); + let snippetsFile2 = new SnippetsFile("/somepath/b.code-snippets", []); + let extension = new Extension( + "robole-snippets-ranger", + "Snippets Ranger", + "/somepath/snippets-ranger" + ); + extension.snippetsFiles = [snippetsFile1, snippetsFile2]; + + let toc = createTableOfContents([], [], [], [extension]); + + let expectedOutput = `

    Table of Contents

      `; + expectedOutput += `
    • Extension Snippets
        `; + expectedOutput += `
      • Snippets Ranger
          `; + expectedOutput += `
        • a
        • `; + expectedOutput += `
        • b
        • `; + expectedOutput += `
      `; + expectedOutput += `
    `; + + assert.strictEqual(toc, expectedOutput); + }); + }); +}); diff --git a/test/view-contrast.html b/test/view-contrast.html deleted file mode 100644 index da8aeaa..0000000 --- a/test/view-contrast.html +++ /dev/null @@ -1,6921 +0,0 @@ - - - - - -

    Snippets Ranger

    -
    -

    Table of Contents

    - -
    -
    -

    User Snippets

    -

    Oucho Gaucho! 🌵 Nothing to round up! 🤠

    -
    -
    -

    Extension Snippets

    -

    markdownlint

    -
    -

    snippets.json

    - Available in the following languages: markdown. -
    PrefixNameDescriptionBodyScopeAction
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    markdownlint-disableinsertMarkdownLintDisableComment - Disables one or more rules by name (MD013), alias (line-length), - or tag (whitespace). Multiple rules are space-delimited (MD018 - MD019). If no rules are specified, all rules are disabled. Takes - effect starting with the line the comment is on. - - <!-- markdownlint-disable ${1:MD000 }-->
    -
    markdownlint-enableinsertMarkdownLintEnableComment - Enables one or more rules by name (MD013), alias (line-length), - or tag (whitespace). Multiple rules are space-delimited (MD018 - MD019). If no rules are specified, all rules are enabled. Takes - effect starting with the line the comment is on. - - <!-- markdownlint-enable ${1:MD000 }-->
    -
    markdownlint-disable-fileinsertMarkdownLintDisableFileComment - Disables one or more rules by name (MD013), alias (line-length), - or tag (whitespace). Multiple rules are space-delimited (MD018 - MD019). If no rules are specified, all rules are disabled. - Applies to the entire file. - - <!-- markdownlint-disable-file ${1:MD000 }-->
    -
    markdownlint-enable-fileinsertMarkdownLintEnableFileComment - Enables one or more rules by name (MD013), alias (line-length), - or tag (whitespace). Multiple rules are space-delimited (MD018 - MD019). If no rules are specified, all rules are enabled. - Applies to the entire file. - - <!-- markdownlint-enable-file ${1:MD000 }-->
    -
    markdownlint-captureinsertMarkdownLintCaptureComment - Captures the current rule configuration. Takes effect starting - with the line the comment is on. - - <!-- markdownlint-capture -->
    -
    markdownlint-restoreinsertMarkdownLintRestoreComment - Restores the most recently captured rule configuration. Defaults - to the document's initial configuration. Takes effect starting - with the line the comment is on. - - <!-- markdownlint-restore -->
    -
    markdownlint-configure-fileinsertMarkdownLintConfigureFileComment - Configures one or more rules by name (MD013), alias - (line-length), or tag (whitespace) using the same JSON format as - the "markdownlint.config" object. Applies to the entire file. - - <!-- markdownlint-configure-file { ${1:"MD013": { - "line_length": 100 \}} } -->
    -
    - -

    - ES7 React/Redux/GraphQL/React-Native snippets -

    -
    -

    snippets.json

    - Available in the following languages: javascript, javascriptreact, - typescript, typescriptreact. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    impimport - import ${2:moduleName} from '${1:module}'$0
    -
    imnimportNoModuleName - import '${1:module}'$0
    -
    imdimportDestructing - import { $2 } from '${1:module}'$0
    -
    imeimportEverything - import * as ${2:alias} from '${1:module}'$0
    -
    imaimportAs - import { ${2:originalName} as ${3:alias} } from - '${1:module}'$0
    -
    expexportDefault - export default $1$0
    -
    exdexportDestructing - export { $2 } from '${1:module}'$0
    -
    exaexportAs - export { ${2:originalName} as ${3:alias} } from - '${1:module}'$0
    -
    enfexportNamedFunctionExport named function in ES7 syntax - export const ${1:functionName} = (${2:params}) => {
    - $0
    }

    -
    edfexportDefaultFunctionExport default function in ES7 syntax - export default (${1:params}) => {
    - $0
    }

    -
    metmethodCreates a method inside a class in ES7 syntax - ${1:methodName} = (${2:params}) => {
    - ${0}
    }

    -
    pgepropertyGetCreates a getter property inside a class in ES7 syntax - get ${1:propertyName}() {
    - return this.${0}
    }

    -
    psepropertySetCreates a setter property inside a class in ES7 syntax - set ${1:propertyName}(${2:value}) {
    - ${0}
    }

    -
    freforEachCreates a forEach statement in ES7 syntax - ${1:array}.forEach(${2:currentItem} => {
    - ${0}
    })

    -
    fofforOfIterating over property names of iterable objects - for(let ${1:item} of ${2:object}) {
    - ${0}
    }

    -
    finforInIterating over property values of iterable objects - for(let ${1:item} in ${2:object}) {
    - ${0}
    }

    -
    anfnanonymousFunctionCreates an anonymous function in ES7 syntax - (${1:params}) => {
    - ${2}
    }

    -
    nfnnamedFunctionCreates a named function in ES7 syntax - const ${1:name} = (${2:params}) => {
    - ${3}
    }

    -
    dobdestructingObject - Creates and assigns a local variable using object destructing - - const {${1:propertyName}} = ${2:objectToDestruct}
    -
    dardestructingArray - Creates and assigns a local variable using array destructing - - const [${1:propertyName}] = ${2:arrayToDestruct}
    -
    stisetInterval - Executes the given function at specified intervals in ES7 syntax - - setInterval(() => {
    - ${2}
    }, ${0:intervalInms})

    -
    stosetTimeOut - Executes the given function after the specified delay in ES7 - syntax - - setTimeout(() => {
    - ${2}
    }, ${1:delayInms})

    -
    prompromise - Creates and returns a new Promise in the standard ES7 syntax - - return new Promise((resolve, reject) => {
    - ${1}
    })

    -
    casconsoleAssert - If the specified expression is false, the message is written to - the console along with a stack trace - - console.assert(${1:expression}, ${2:object})
    -
    cclconsoleClearClears the console - console.clear()
    -
    ccoconsoleCount - Writes the the number of times that count() has been invoked at - the same line and with the same label - - console.count(${1:label})
    -
    cdiconsoleDir - Prints a JavaScript representation of the specified object - - console.dir(${1:object})
    -
    cerconsoleError - Displays a message in the console and also includes a stack - trace from where the method was called - - console.error(${1:object})
    -
    cgrconsoleGroup - Groups and indents all following output by an additional level, - until console.groupEnd() is called. - - console.group("${1:label}")
    -
    cgeconsoleGroupEndCloses out the corresponding console.group(). - console.groupEnd()
    -
    clgconsoleLogDisplays a message in the console - console.log(${1:object})
    -
    ctrconsoleTrace - Prints a stack trace from the point where the method was called - - console.trace(${1:object})
    -
    cloconsoleLogObjectLogs property with name. - console.log('${1:object}', ${1:object})
    -
    ctmconsoleTimeConsole time wrapper - console.time('${1:object}')
    -
    cteconsoleTimeEndConsole time end wrapper - console.timeEnd('${1:object}')
    -
    cwaconsoleWarn - Displays a message in the console but also displays a yellow - warning icon along with the logged message - - console.warn(${1:object})
    -
    cinconsoleInfo - Displays a message in the console but also displays a blue - information icon along with the logged message - - console.info(${1:object})
    -
    cpdestructProps - Creates and assigns a local variable using props destructing - - const { $1 } = this.props
    -
    csdestructState - Creates and assigns a local variable using state destructing - - const { $1 } = this.state
    -
    imrimport React - import React from 'react'

    -
    imrdimport ReactDOM - import ReactDOM from 'react-dom'

    -
    imrcimport React, { Component } - import React, { Component } from 'react'

    -
    imrcpimport React, { Component } & PropTypes - import React, { Component } from 'react'
    import - PropTypes from 'prop-types'

    -
    imrpcimport React, { PureComponent } - import React, { PureComponent } from 'react'

    -
    imrpcpimport React, { PureComponent } & PropTypes - import React, { PureComponent } from 'react'
    import - PropTypes from 'prop-types'

    -
    imrmimport React, { memo } - import React, { memo } from 'react'

    -
    imrmpimport React, { memo } & PropTypes - import React, { memo } from 'react'
    import PropTypes - from 'prop-types'

    -
    imrsimport React, {useState} - import React, { useState } from 'react'

    -
    imrseimport React, {useState, useEffect} - import React, { useState, useEffect } from 'react'

    -
    imptimport PropTypes - import PropTypes from 'prop-types'

    -
    imrrimport React Router - import { BrowserRouter as Router, Route, NavLink } from - 'react-router-dom'

    -
    imbrimport React Browser Router - import { BrowserRouter as Router } from 'react-router-dom'

    -
    imbrrimport React Browser Router - Route - import { Route } from 'react-router-dom'

    -
    imbrcimport React Browser Router - Route Combo - import { Route, Switch, NavLink, Link } from - 'react-router-dom'

    -
    imbrsimport React Browser Router - Switch - import { Switch } from 'react-router-dom'

    -
    imbrlimport React Browser Router - Link - import { Link } from 'react-router-dom'

    -
    imbrnlimport React Browser Router - NavLink - import { NavLink } from 'react-router-dom'

    -
    reduximport redux statement - import { connect } from 'react-redux'

    -
    rccreactClassCompomentCreates a React component class with ES7 module system - import React, { Component } from 'react'

    export - default class ${1:${TM_FILENAME_BASE}} extends Component {
    - render() {
    - return (
    - <div>
    - $0
    - </div>
    - )
    - }
    }

    -
    rcereactClassExportComponentCreates a React component class with ES7 module system - import React, { Component } from 'react'

    export - class ${1:${TM_FILENAME_BASE}} extends Component {
    - render() {
    - return (
    - <div>
    - $0
    - </div>
    - )
    - }
    }

    export default ${1:${TM_FILENAME_BASE}}

    -
    rfcereactFunctionalExportComponent - Creates a React Functional Component with ES7 module system - - import React from 'react'

    function - ${1:${TM_FILENAME_BASE}}() {
    - return (
    - <div>
    - $0
    - </div>
    - )
    }

    export default ${1:${TM_FILENAME_BASE}}

    -
    rfcreactFunctionalComponent - Creates a React Functional Component with ES7 module system - - import React from 'react'

    export default function - ${1:${TM_FILENAME_BASE}}() {
    - return (
    - <div>
    - $0
    - </div>
    - )
    }

    -
    rfcpreactFunctionalComponentWithPropTypes - Creates a React Functional Component with ES7 module system with - PropTypes - - import React from 'react'
    import PropTypes from - 'prop-types'

    function - ${1:${TM_FILENAME_BASE}}(props) {
    - return (
    - <div>
    - $0
    - </div>
    - )
    }

    ${1:${TM_FILENAME_BASE}}.propTypes = {

    }

    export - default ${1:${TM_FILENAME_BASE}}


    -
    rafcereactArrowFunctionExportComponent - Creates a React Arrow Function Component with ES7 module system - - import React from 'react'

    const - ${1:${TM_FILENAME_BASE}} = () => {
    - return (
    - <div>
    - $0
    - </div>
    - )
    }

    export default ${1:${TM_FILENAME_BASE}}

    -
    rafcreactArrowFunctionComponent - Creates a React Arrow Function Component with ES7 module system - - import React from 'react'

    export const - ${1:${TM_FILENAME_BASE}} = () => {
    - return (
    - <div>
    - $0
    - </div>
    - )
    }

    -
    rafcpreactArrowFunctionComponentWithPropTypes - Creates a React Arrow Function Component with ES7 module system - with PropTypes - - import React from 'react'
    import PropTypes from - 'prop-types'

    const ${1:${TM_FILENAME_BASE}} = props - => {
    - return (
    - <div>
    - $0
    - </div>
    - )
    }

    ${1:${TM_FILENAME_BASE}}.propTypes = {

    }

    export - default ${1:${TM_FILENAME_BASE}}

    -
    rcepreactClassExportComponentWithPropTypesCreates a React component class with ES7 module system - import React, { Component } from 'react'
    import - PropTypes from 'prop-types'

    export class - ${1:${TM_FILENAME_BASE}} extends Component {
    - static propTypes = {

    - }

    - render() {
    - return (
    - <div>
    - $0
    - </div>
    - )
    - }
    }

    export default ${1:${TM_FILENAME_BASE}}

    -
    rpcreactClassPureComponent - Creates a React pure component class with ES7 module system - - import React, { PureComponent } from 'react'

    export - default class ${1:${TM_FILENAME_BASE}} extends PureComponent - {
    - render() {
    - return (
    - <div>
    - $0
    - </div>
    - )
    - }
    }

    -
    rpcereactClassExportPureComponent - Creates a React pure component class with ES7 module system - export - - import React, { PureComponent } from 'react'

    export - class ${1:${TM_FILENAME_BASE}} extends PureComponent {
    - render() {
    - return (
    - <div>
    - $0
    - </div>
    - )
    - }
    }

    export default ${1:$TM_FILENAME_BASE}

    -
    rpcpreactClassPureComponentWithPropTypesCreates a React component class with ES7 module system - import React, { PureComponent } from 'react'
    import - PropTypes from 'prop-types'

    export default class - ${1:${TM_FILENAME_BASE}} extends PureComponent {
    - static propTypes = {

    - }

    - render() {
    - return (
    - <div>
    - $0
    - </div>
    - )
    - }
    }

    -
    rmcreactFunctionMemoComponent - Creates a React Memo Function Component with ES7 module system - - import React, { memo } from 'react'

    export default - memo(function ${1:${TM_FILENAME_BASE}}() {
    - return (
    - <div>
    - $0
    - </div>
    - )
    })

    -
    rmcpreactFunctionMemoComponentWithPropTypes - Creates a React Memo Function Component with ES7 module system - with PropTypes - - import React, { memo } from 'react'
    import PropTypes - from 'prop-types'

    const ${1:${TM_FILENAME_BASE}} = - memo(function ${1:${TM_FILENAME_BASE}}(props) {
    - return (
    - <div>
    - $0
    - </div>
    - )
    })

    ${1:${TM_FILENAME_BASE}}.propTypes = {

    }

    export - default ${1:${TM_FILENAME_BASE}}

    -
    rccpreactClassCompomentPropTypes - Creates a React component class with PropTypes and ES7 module - system - - import React, { Component } from 'react'
    import - PropTypes from 'prop-types'

    export default class - ${1:${TM_FILENAME_BASE}} extends Component {
    - static propTypes = {
    - ${2:prop}: ${3:PropTypes}
    - }

    - render() {
    - return (
    - <div>
    - $0
    - </div>
    - )
    - }
    }

    -
    rcreduxreactClassCompomentRedux - Creates a React component class with connected redux and ES7 - module system - - import React, { Component } from 'react'
    import { - connect } from 'react-redux'

    export class - ${1:${TM_FILENAME_BASE}} extends Component {
    - render() {
    - return (
    - <div>
    - $0
    - </div>
    - )
    - }
    }

    const mapStateToProps = (state) => - ({
    -
    })

    const mapDispatchToProps = {
    -
    }

    export default connect(mapStateToProps, - mapDispatchToProps)(${1:${TM_FILENAME_BASE}})

    -
    rcreduxpreactClassCompomentReduxPropTypes - Creates a React component class with PropTypes with connected - redux and ES7 module system - - import React, { Component } from 'react'
    import - PropTypes from 'prop-types'
    import { connect } from - 'react-redux'

    export class ${1:${TM_FILENAME_BASE}} - extends Component {
    - static propTypes = {
    - ${2:prop}: ${3:PropTypes}
    - }

    - render() {
    - return (
    - <div>
    - $0
    - </div>
    - )
    - }
    }

    const mapStateToProps = (state) => - ({
    -
    })

    const mapDispatchToProps = {
    -
    }

    export default connect(mapStateToProps, - mapDispatchToProps)(${1:${TM_FILENAME_BASE}})

    -
    rfcreduxreactFunctionalCompomentRedux - Creates a React functional component with connected redux and - ES7 module system - - import React, { Component } from 'react'
    import { - connect } from 'react-redux'

    export const - ${1:${TM_FILENAME_BASE}} = () => {
    - return (
    - <div>
    - $0
    - </div>
    - )
    }

    const mapStateToProps = (state) => - ({
    -
    })

    const mapDispatchToProps = {
    -
    }

    export default connect(mapStateToProps, - mapDispatchToProps)(${1:${TM_FILENAME_BASE}})

    -
    rfcreduxpreactFunctionalCompomentReduxPropTypes - Creates a React functional component with PropTypes with - connected redux and ES7 module system - - import React, { Component } from 'react'
    import - PropTypes from 'prop-types'
    import { connect } from - 'react-redux'

    export const ${1:${TM_FILENAME_BASE}} - = () => {
    - return (
    - <div>
    - $0
    - </div>
    - )
    }

    ${1:${TM_FILENAME_BASE}}.propTypes = {
    - ${2:prop}: ${3:PropTypes}
    }

    const - mapStateToProps = (state) => ({
    -
    })

    const mapDispatchToProps = {
    -
    }

    export default connect(mapStateToProps, - mapDispatchToProps)(${1:${TM_FILENAME_BASE}})

    -
    reduxmapmappingToProps - const mapStateToProps = (state) => ({
    - ${1}
    })

    const mapDispatchToProps = {
    -
    }

    -
    rconstclassConstructor - Adds a default constructor for it('', () => {})the class that - contains props as arguments - - constructor(props) {
    - super(props)

    - this.state = {
    - $0
    - }
    }

    -
    estemptyStateCreates empty state object. To be used in a constructor. - state = {
    - $1
    }

    -
    cwmcomponentWillMount - DEPRECATED!!!. Invoked once, both on the client and server, - immediately before the initial rendering occurs - - componentWillMount() {
    - $0
    }

    -
    cdmcomponentDidMount - Invoked once, only on the client (not on the server), - immediately after the initial rendering occurs. - - componentDidMount() {
    - $0
    }

    -
    cwrcomponentWillReceiveProps - DEPRECATED!!!. Invoked when a component is receiving new props. - This method is not called for the initial render. - - componentWillReceiveProps(nextProps) {
    - $0
    }

    -
    scushouldComponentUpdate - Invoked before rendering when new props or state are being - received. - - shouldComponentUpdate(nextProps, nextState) {
    - $0
    }

    -
    cwupcomponentWillUpdate - DEPRECATED!!!. Invoked immediately before rendering when new - props or state are being received. - - componentWillUpdate(nextProps, nextState) {
    - $0
    }

    -
    cdupcomponentDidUpdate - Invoked immediately after the component's updates are flushed to - the DOM. - - componentDidUpdate(prevProps, prevState) {
    - $0
    }

    -
    cwuncomponentWillUnmount - Invoked immediately before a component is unmounted from the - DOM. - - componentWillUnmount() {
    - $0
    }

    -
    gdsfpgetDerivedStateFromProps - Invoked right before calling the render method, both on the - initial mount and on subsequent updates. - - static getDerivedStateFromProps(props, state) {
    - ${1}
    }
    -
    gsbugetSnapshotBeforeUpdate - Called right before mutations are made (e.g. before the DOM is - updated) - - getSnapshotBeforeUpdate = (prevProps, prevState) => {
    - $0
    }

    -
    rencomponentRenderBasic render. - render() {
    - return (
    - <div>
    - $0
    - </div>
    - )
    }
    -
    rcontextcreateContextCreate React context - const ${1:contextName} = React.createContext()

    -
    crefcreateRefCreate ref statement used inside constructor - this.${1:refName}Ref = React.createRef()

    -
    frefforwardRefForward ref statement used inside component - const ref = React.createRef()

    -
    sstcomponentSetStateObjectPerforms a shallow merge of nextState into current state - this.setState({$0})
    -
    ssfcomponentSetStateFuncPerforms a shallow merge of nextState into current state - this.setState((state, props) => { return { $0 }})

    -
    propscomponentPropsAccess component's props - this.props.$0
    -
    statecomponentState - this.state.$0
    -
    bndbindThisBinds this to a method - this.${1:methodName} = this.${1:methodName}.bind(this)$0
    -
    rxactionreduxAction - export const ${1:actionName} = (payload) => ({
    - type: ${3:type},
    - payload
    })

    -
    rxconstreduxConst - export const ${1:constantName} = '${1:constantName}'
    -
    rxreducerreduxReducer - const initialState = {

    }

    export default - (state = initialState, { type, payload }) => {
    - switch (type) {

    - case ${1:typeName}:
    - return { ...state, ...payload }

    - default:
    - return state
    - }
    }

    -
    rxselectreduxSelector - import { createSelector } from 'reselect'

    export - const ${1:selectorName} = state => state.${2:selector}

    -
    rncreactNativeComponent - import React, { Component } from 'react'
    import { Text, - View } from 'react-native'

    export default class - ${1:${TM_FILENAME_BASE}} extends Component {
    - render() {
    - return (
    - <View>
    - <Text> ${2:textInComponent} </Text>
    - </View>
    - )
    - }
    }

    -
    rncsreactNativeComponentWithStyles - import React, { Component } from 'react'
    import { Text, - StyleSheet, View } from 'react-native'

    export - default class ${1:${TM_FILENAME_BASE}} extends Component {
    - render() {
    - return (
    - <View>
    - <Text> ${2:textInComponent} </Text>
    - </View>
    - )
    - }
    }

    const styles = StyleSheet.create({})

    -
    rncereactNativeComponentExport - import React, { Component } from 'react'
    import { Text, - View } from 'react-native'

    export class - ${1:${TM_FILENAME_BASE}} extends Component {
    - render() {
    - return (
    - <View>
    - <Text> ${2:textInComponent} </Text>
    - </View>
    - )
    - }
    }

    export default ${1:${TM_FILENAME_BASE}}

    -
    rnpcreactNativePureComponent - import React, { PureComponent } from 'react'
    import { - Text, View } from 'react-native'

    export default - class ${1:${TM_FILENAME_BASE}} extends PureComponent {
    - render() {
    - return (
    - <View>
    - <Text> ${2:textInComponent} </Text>
    - </View>
    - )
    - }
    }

    -
    rnpcereactNativePureComponentExport - import React, { PureComponent } from 'react'
    import { - Text, View } from 'react-native'

    export class - ${1:${TM_FILENAME_BASE}} extends PureComponent {
    - render() {
    - return (
    - <View>
    - <Text> ${2:textInComponent} </Text>
    - </View>
    - )
    - }
    }

    export default ${1:${TM_FILENAME_BASE}}

    -
    rncreduxreactNativeClassComponentRedux - Creates a React Native component class with PropTypes with - connected redux and ES7 module system - - import React, { Component } from 'react'
    import { View, - Text } from 'react-native'
    import PropTypes from - 'prop-types'
    import { connect } from 'react-redux'

    export - class ${1:${TM_FILENAME_BASE}} extends Component {
    - static propTypes = {
    - ${2:prop}: ${3:PropTypes}
    - }

    - render() {
    - return (
    - <View>
    - <Text> ${2:textInComponent} </Text>
    - </View>
    - )
    - }
    }

    const mapStateToProps = (state) => - ({
    -
    })

    const mapDispatchToProps = {
    -
    }

    export default connect(mapStateToProps, - mapDispatchToProps)(${1:${TM_FILENAME_BASE}})

    -
    rnfereactNativeFunctionalExportComponent - import React from 'react'
    import { View, Text } from - 'react-native'

    const ${1:${TM_FILENAME_BASE}} = () - => {
    - return (
    - <View>
    - <Text>$0</Text>
    - </View>
    - )
    }

    export default ${1:${TM_FILENAME_BASE}}

    -
    rnfesreactNativeFunctionalExportComponentWithStyles - import React from 'react'
    import { StyleSheet, Text, - View } from 'react-native'

    const - ${1:${TM_FILENAME_BASE}} = () => {
    - return (
    - <View>
    - <Text>$0</Text>
    - </View>
    - )
    }

    export default ${1:${TM_FILENAME_BASE}}

    const - styles = StyleSheet.create({})

    -
    rnfreactNativeFunctionalComponent - import React from 'react'
    import { View, Text } from - 'react-native'

    export default function - ${1:${TM_FILENAME_BASE}}() {
    - return (
    - <View>
    - <Text>$0</Text>
    - </View>
    - )
    }

    -
    rnfsreactNativeFunctionalComponentWithStyles - import React from 'react'
    import { StyleSheet, Text, - View } from 'react-native'

    export default function - ${1:${TM_FILENAME_BASE}}() {
    - return (
    - <View>
    - <Text>$0</Text>
    - </View>
    - )
    }

    const styles = StyleSheet.create({})

    -
    imrnreactNativeImport - import { ${1:moduleName} } from 'react-native'
    -
    rnstylereactNativeStyles - const styles = StyleSheet.create({
    - ${1:style}
    })

    -
    ptapropTypeArrayArray prop type - PropTypes.array,
    -
    ptarpropTypeArrayRequiredArray prop type required - PropTypes.array.isRequired,
    -
    ptbpropTypeBoolBool prop type - PropTypes.bool,
    -
    ptbrpropTypeBoolRequiredBool prop type required - PropTypes.bool.isRequired,
    -
    ptfpropTypeFuncFunc prop type - PropTypes.func,
    -
    ptfrpropTypeFuncRequiredFunc prop type required - PropTypes.func.isRequired,
    -
    ptnpropTypeNumberNumber prop type - PropTypes.number,
    -
    ptnrpropTypeNumberRequiredNumber prop type required - PropTypes.number.isRequired,
    -
    ptopropTypeObjectObject prop type - PropTypes.object,
    -
    ptorpropTypeObjectRequiredObject prop type required - PropTypes.object.isRequired,
    -
    ptspropTypeStringString prop type - PropTypes.string,
    -
    ptsrpropTypeStringRequiredString prop type required - PropTypes.string.isRequired,
    -
    ptndpropTypeNode - Anything that can be rendered: numbers, strings, elements or an - array - - PropTypes.node,
    -
    ptndrpropTypeNodeRequired - Anything that can be rendered: numbers, strings, elements or an - array required - - PropTypes.node.isRequired,
    -
    ptelpropTypeElementReact element prop type - PropTypes.element,
    -
    ptelrpropTypeElementRequiredReact element prop type required - PropTypes.element.isRequired,
    -
    ptipropTypeInstanceOfIs an instance of a class prop type - PropTypes.instanceOf($0),
    -
    ptirpropTypeInstanceOfRequiredIs an instance of a class prop type required - PropTypes.instanceOf($0).isRequired,
    -
    ptepropTypeEnum - Prop type limited to specific values by treating it as an enum - - PropTypes.oneOf(['$0']),
    -
    pterpropTypeEnumRequired - Prop type limited to specific values by treating it as an enum - required - - PropTypes.oneOf(['$0']).isRequired,
    -
    ptetpropTypeOneOfTypeAn object that could be one of many types - PropTypes.oneOfType([
    - $0
    ]),
    -
    ptetrpropTypeOneOfTypeRequiredAn object that could be one of many types required - PropTypes.oneOfType([
    - $0
    ]).isRequired,
    -
    ptaopropTypeArrayOfAn array of a certain type - PropTypes.arrayOf($0),
    -
    ptaorpropTypeArrayOfRequiredAn array of a certain type required - PropTypes.arrayOf($0).isRequired,
    -
    ptoopropTypeObjectOfAn object with property values of a certain type - PropTypes.objectOf($0),
    -
    ptoorpropTypeObjectOfRequiredAn object with property values of a certain type required - PropTypes.objectOf($0).isRequired,
    -
    ptshpropTypeShapeAn object taking on a particular shape - PropTypes.shape({
    - $0
    }),
    -
    ptshrpropTypeShapeRequiredAn object taking on a particular shape required - PropTypes.shape({
    - $0
    }).isRequired,
    -
    ptexpropTypeExactAn object with warnings on extra properties - PropTypes.exact({
    - $0
    }),
    -
    ptexrpropTypeExactRequiredAn object with warnings on extra properties required - PropTypes.exact({
    - $0
    }).isRequired,
    -
    ptypesstaticPropTpyes - static propTypes = {
    $0
    }

    -
    ptanypropTypeAnyAny prop type - PropTypes.any,
    -
    cmmbComment Big Block - /**
    - * ${0}
    - */
    -
    descdescribeBlockTesting `describe` block - describe('$1', () => {
    - $0
    })

    -
    testtestBlockTesting `test` block - test('should $1', () => {
    - $0
    })

    -
    testatestAsyncBlockTesting `asynchronous test` block - test('should $1', async () => {
    - $0
    })

    -
    tititBlockTesting `it` block - it('should $1', () => {
    - $0
    })

    -
    titaitAsyncBlockTesting asynchronous `it` block - it('should $1', async () => {
    - $0
    })

    -
    stestsetupReactTest - import React from 'react'
    import renderer from - 'react-test-renderer'

    import { - ${1:${TM_FILENAME_BASE}} } from - '../${1:${TM_FILENAME_BASE}}'

    describe('<${1:${TM_FILENAME_BASE}} - />', () => {
    - const defaultProps = {}
    - const wrapper = renderer.create(<${1:${TM_FILENAME_BASE}} - {...defaultProps} />)

    - test('render', () => {
    - expect(wrapper).toMatchSnapshot()
    - })
    })

    -
    sntestsetupReactNativeTest - import 'react-native'
    import React from 'react'
    import - renderer from 'react-test-renderer'

    import - ${1:${TM_FILENAME_BASE}} from '../${1:${TM_FILENAME_BASE}}'

    describe('<${1:${TM_FILENAME_BASE}} - />', () => {
    - const defaultProps = {}
    - const wrapper = renderer.create(<${1:${TM_FILENAME_BASE}} - {...defaultProps} />)

    - test('render', () => {
    - expect(wrapper).toMatchSnapshot()
    - })
    })

    -
    srtestsetupReactComponentTestWithReduxCreate test component - import React from 'react'
    import renderer from - 'react-test-renderer'
    import { Provider } from - 'react-redux'

    import store from 'src/store'
    import - { ${1:${TM_FILENAME_BASE}} } from - '../${1:${TM_FILENAME_BASE}}'

    describe('<${1:${TM_FILENAME_BASE}} - />', () => {
    - const defaultProps = {}
    - const wrapper = renderer.create(
    - <Provider store={store}>
    - <${1:${TM_FILENAME_BASE}} {...defaultProps} />
    - </Provider>,
    - )

    - test('render', () => {
    - expect(wrapper).toMatchSnapshot()
    - })
    })

    -
    snrtestsetupReactNativeTestWithRedux - import 'react-native'
    import React from 'react'
    import - renderer from 'react-test-renderer'
    import { Provider } - from 'react-redux'

    import store from 'src/store'
    import - ${1:${TM_FILENAME_BASE}} from '../${1:${TM_FILENAME_BASE}}'

    describe('<${1:${TM_FILENAME_BASE}} - />', () => {
    - const defaultProps = {}
    - const wrapper = renderer.create(
    - <Provider store={store}>
    - <${1:${TM_FILENAME_BASE}} {...defaultProps} />
    - </Provider>,
    - )

    - test('render', () => {
    - expect(wrapper).toMatchSnapshot()
    - })
    })

    -
    graphqlgraphQLForComponent - import { compose, graphql } from 'react-apollo'

    -
    expgqlexportGraphQL - export default compose(
    - graphql(${1:queryOrMutation}, { name: ${2:name} }),
    )(${1:${TM_FILENAME_BASE}})
    -
    hocreduxhocComponentWithRedux - import React from 'react'
    import PropTypes from - 'prop-types'
    import { connect } from 'react-redux'

    export - const mapStateToProps = state => ({

    })

    export - const mapDispatchToProps = {
    -
    }

    export const ${1:hocComponentName} = - (WrappedComponent) => {
    - const hocComponent = ({ ...props }) => <WrappedComponent - {...props} />

    - hocComponent.propTypes = {
    - }

    - return hocComponent
    }

    export default - WrapperComponent => connect(mapStateToProps, - mapDispatchToProps)(${1:hocComponentName}(WrapperComponent))

    -
    hochocComponent - import React from 'react'
    import PropTypes from - 'prop-types'

    export default (WrappedComponent) - => {
    - const hocComponent = ({ ...props }) => <WrappedComponent - {...props} />

    - hocComponent.propTypes = {
    - }

    - return hocComponent
    }

    -
    useStateuseState - const [${1:state}, set${1/(.*)/${1:/capitalize}/}] = - useState(${2:initialState})
    -
    useEffectuseEffect - useEffect(() => {
    - ${1:effect}
    - return () => {
    - ${2:cleanup}
    - }
    }, [${3:input}])
    -
    useContextuseContext - const ${1:context} = useContext(${2:contextValue})
    -
    useReduceruseReducer - const [state, dispatch] = useReducer(${1:reducer}, - ${2:initialState}, ${3:init})
    -
    useCallbackuseCallback - useCallback(
    - () => {
    - ${1:callback}
    - },
    - [${2:input}],
    )
    -
    useMemouseMemo - useMemo(() => ${1:function}, ${2:input})
    -
    useRefuseRef - const ${1:ref} = useRef(${2:initialValue})
    -
    useImperativeHandleuseImperativeHandle - useImperativeHandle(
    - ${1:ref},
    - () => {
    - ${2:handler}
    - },
    - [${3:input}],
    )
    -
    useDebugValueuseDebugValue - useDebugValue(${1:value})
    -
    useLayoutEffectuseLayoutEffect - useLayoutEffect(() => {
    - ${1:effect}
    - return () => {
    - ${2:cleanup}
    - };
    }, [${3:input}])
    -
    useSelectoruseSelector - const ${1:state} = useSelector(state => - state.${1:state})
    -
    useDispatchuseDispatch - const dispatch = useDispatch(${1:function})
    -
    tpftypeof - typeof ${0}
    -
    -
    -
    -

    ts-snippets.json

    - Available in the following languages: typescript, typescriptreact. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    tsrcctypeScriptReactClassComponent - Creates a React component class with ES7 module system and - TypeScript interfaces - - import React, { Component } from 'react'

    interface - Props {
    -
    }
    interface State {
    -
    }

    export default class - ${1:${TM_FILENAME_BASE}} extends Component<Props, State> - {
    - state = {}

    - render() {
    - return (
    - <div>
    - $0
    - </div>
    - )
    - }
    }

    -
    tsrcetypeScriptReactClassExportComponent - Creates a React component class with ES7 module system and - TypeScript interfaces - - import React, { Component } from 'react'

    interface - Props {
    -
    }
    interface State {
    -
    }

    class ${1:${TM_FILENAME_BASE}} extends - Component<Props, State> {
    - state = {}

    - render() {
    - return (
    - <div>
    - $0
    - </div>
    - )
    - }
    }

    export default ${1:${TM_FILENAME_BASE}}

    -
    tsrfcetypeScriptReactFunctionalExportComponent - Creates a React Functional Component with ES7 module system and - TypeScript interface - - import React, { ReactElement } from 'react'

    interface - Props {
    -
    }

    function ${1:${TM_FILENAME_BASE}}({}: - Props): ReactElement {
    - return (
    - <div>
    - $0
    - </div>
    - )
    }

    export default ${1:${TM_FILENAME_BASE}}

    -
    tsrfctypeScriptReactFunctionalComponent - Creates a React Functional Component with ES7 module system and - TypeScript interface - - import React, { ReactElement } from 'react'

    interface - Props {
    -
    }

    export default function - ${1:${TM_FILENAME_BASE}}({}: Props): ReactElement {
    - return (
    - <div>
    - $0
    - </div>
    - )
    }

    -
    tsrafcetypeScriptReactArrowFunctionExportComponent - Creates a React Arrow Function Component with ES7 module system - and TypeScript interface - - import React from 'react'

    interface Props {
    -
    }

    const ${1:${TM_FILENAME_BASE}} = (props: - Props) => {
    - return (
    - <div>
    - $0
    - </div>
    - )
    }

    export default ${1:${TM_FILENAME_BASE}}

    -
    tsrafctypeScriptReactArrowFunctionComponent - Creates a React Arrow Function Component with ES7 module system - and TypeScript interface - - import React from 'react'

    interface Props {
    -
    }

    export const ${1:${TM_FILENAME_BASE}} = - (props: Props) => {
    - return (
    - <div>
    - $0
    - </div>
    - )
    }

    -
    tsrpctypeScriptReactClassPureComponent - Creates a React pure component class with ES7 module system and - TypeScript interface - - import React, { PureComponent } from 'react'

    interface - Props {
    -
    }

    export default class - ${1:${TM_FILENAME_BASE}} extends PureComponent<Props> - {
    - render() {
    - return (
    - <div>
    - $0
    - </div>
    - )
    - }
    }

    -
    tsrpcetypeScriptReactClassExportPureComponent - Creates a React pure component class with ES7 module system and - TypeScript interface - - import React, { PureComponent } from 'react'

    interface - Props {
    -
    }

    class ${1:${TM_FILENAME_BASE}} extends - PureComponent<Props> {
    - render() {
    - return (
    - <div>
    - $0
    - </div>
    - )
    - }
    }

    export default ${1:${TM_FILENAME_BASE}}

    -
    tsrmctypeScriptReactFunctionMemoComponent - Creates a React Memo Function Component with ES7 module system - and TypeScript interface - - import React, { memo } from 'react'

    interface - Props {
    -
    }

    export default memo(function - ${1:${TM_FILENAME_BASE}}({}: Props) {
    - return (
    - <div>
    - $0
    - </div>
    - )
    })

    -
    tsrcreduxtypeScriptReactClassCompomentRedux - Creates a React component class with PropTypes with connected - redux and ES7 module system and TypeScript interfaces - - import React, { Component } from 'react'
    import { - connect } from 'react-redux'

    interface Props {
    -
    }
    interface State {
    -
    }

    export class ${1:${TM_FILENAME_BASE}} - extends Component<Props, State> {
    - state = {}

    - render() {
    - return (
    - <div>
    - $0
    - </div>
    - )
    - }
    }

    const mapStateToProps = (state) => - ({
    -
    })

    const mapDispatchToProps = {
    -
    }

    export default connect(mapStateToProps, - mapDispatchToProps)(${1:${TM_FILENAME_BASE}})

    -
    tsrnftypescriptReactNativeArrowFunctionComponent - Creates a React Native Arrow Function Component with ES7 module - system and TypeScript interface - - import React from 'react'
    import { View, Text } from - 'react-native'

    interface Props {
    -
    }

    const ${1:${TM_FILENAME_BASE}} = (props: - Props) => {
    - return (
    - <View>
    - <Text>$0</Text>
    - </View>
    - )
    }

    export default ${1:${TM_FILENAME_BASE}}

    -
    tsrnfitypescriptReactNativeArrowFunctionComponentNamedProps - Creates a React Native Arrow Function Component with ES7 module - system and named TypeScript interface - - import React from 'react'
    import { View } from - 'react-native'

    interface - ${1:${TM_FILENAME_BASE}}Props {
    -
    }

    const ${1:${TM_FILENAME_BASE}}: - React.FunctionComponent<${1:${TM_FILENAME_BASE}}Props> = - (props) => {
    - return (
    - <View>
    - $0
    - </View>
    - )
    }

    export default ${1:${TM_FILENAME_BASE}}

    -
    tsrnfstypescriptReactNativeArrowFunctionComponentWithStyles - Creates a React Native Arrow Function Component with ES7 module - system, TypeScript interface and StyleSheet - - import React from 'react'
    import { StyleSheet, Text, - View } from 'react-native'

    interface Props {
    -
    }

    const ${1:${TM_FILENAME_BASE}} = (props: - Props) => {
    - return (
    - <View>
    - <Text>$0</Text>
    - </View>
    - )
    }

    export default ${1:${TM_FILENAME_BASE}}

    const - styles = StyleSheet.create({})

    -
    expintExport interface - export interface ${1:${TM_FILENAME_BASE}} {$0}
    -
    exptpExport type - export type ${1:${TM_FILENAME_BASE}} = {$0}
    -
    -
    -

    Markdown Snippets

    -
    -

    snippets.code-snippets

    - Available in the following languages: markdown. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    heading1Insert heading level 1Insert heading level 1 - # ${1:${TM_SELECTED_TEXT}}
    -
    heading2Insert heading level 2Insert heading level 2 - ## ${1:${TM_SELECTED_TEXT}}
    -
    heading3Insert heading level 3Insert heading level 3 - ### ${1:${TM_SELECTED_TEXT}}
    -
    heading4Insert heading level 4Insert heading level 4 - #### ${1:${TM_SELECTED_TEXT}}
    -
    heading5Insert heading level 5Insert heading level 5 - ##### ${1:${TM_SELECTED_TEXT}}
    -
    heading6Insert heading level 6Insert heading level 6 - ###### ${1:${TM_SELECTED_TEXT}}
    -
    strikethroughInsert strikethroughInsert strikethrough - ~~${1:${TM_SELECTED_TEXT}}~~
    -
    taskInsert task listInsert task list - - [${1| ,x|}] ${2:text}
    - [${3| ,x|}] ${4:text}
    ${0}
    -
    tableInsert table - Insert table with 2 rows and 3 columns. First row is heading. - - | ${1:Column1} | ${2:Column2} | ${3:Column3} |
    |-------------- - | -------------- | -------------- |
    | ${4:Item1} | - ${5:Item1} | ${6:Item1} |
    ${0}
    -
    2x1tableInsert 2x1 table - Insert table with 2 rows and 1 column. First row is heading. - - | ${1:Column1} |
    |-------------- |
    | ${2:Item1} - |
    ${0}
    -
    3x1tableInsert 3x1 table - Insert table with 3 rows and 1 column. First row is heading. - - | ${1:Column1} |
    |-------------- |
    | ${2:Item1} - |
    | ${3:Item2} |
    ${0}
    -
    4x1tableInsert 4x1 table - Insert table with 4 rows and 1 column. First row is heading. - - | ${1:Column1} |
    |-------------- |
    | ${2:Item1} - |
    | ${3:Item2} |
    | ${4:Item3} |
    ${0}
    -
    5x1tableInsert 5x1 table - Insert table with 5 rows and 1 column. First row is heading. - - | ${1:Column1} |
    |-------------- |
    | ${2:Item1} - |
    | ${3:Item2} |
    | ${4:Item3} |
    | ${5:Item4} - |
    ${0}
    -
    2x2tableInsert 2x2 table - Insert table with 2 rows and 2 columns. First row is heading. - - | ${1:Column1} | ${2:Column2} |
    |--------------- | - --------------- |
    | ${3:Item1.1} | ${4:Item2.1} |
    ${0}
    -
    3x2tableInsert 3x2 table - Insert table with 3 rows and 2 columns. First row is heading. - - | ${1:Column1} | ${2:Column2} |
    |--------------- | - --------------- |
    | ${3:Item1.1} | ${4:Item2.1} |
    | - ${5:Item1.2} | ${6:Item2.2} |
    ${0}
    -
    4x2tableInsert 4x2 table - Insert table with 4 rows and 2 columns. First row is heading. - - | ${1:Column1} | ${2:Column2} |
    |--------------- | - --------------- |
    | ${3:Item1.1} | ${4:Item2.1} |
    | - ${5:Item1.2} | ${6:Item2.2} |
    | ${7:Item1.3} | - ${8:Item2.3} |
    ${0}
    -
    5x2tableInsert 5x2 table - Insert table with 5 rows and 2 columns. First row is heading. - - | ${1:Column1} | ${2:Column2} |
    |--------------- | - --------------- |
    | ${3:Item1.1} | ${4:Item2.1} |
    | - ${4:Item1.2} | ${5:Item2.2} |
    | ${6:Item1.3} | - ${7:Item2.3} |
    | ${8:Item1.4} | ${9:Item2.4} |
    ${0}
    -
    2x3tableInsert 2x3 table - Insert table with 2 rows and 3 columns. First row is heading. - - | ${1:Column1} | ${2:Column2} | ${3:Column3} |
    |---------------- - | --------------- | --------------- |
    | ${4:Item1.1} | - ${5:Item2.1} | ${6:Item3.1} |
    ${0}
    -
    3x3tableInsert 3x3 table - Insert table with 3 rows and 3 columns. First row is heading. - - | ${1:Column1} | ${2:Column2} | ${3:Column3} |
    |---------------- - | --------------- | --------------- |
    | ${4:Item1.1} | - ${5:Item2.1} | ${6:Item3.1} |
    | ${7:Item1.2} | - ${8:Item2.2} | ${9:Item3.2} |
    ${0}
    -
    4x3tableInsert 4x3 table - Insert table with 4 rows and 3 columns. First row is heading. - - | ${1:Column1} | ${2:Column2} | ${3:Column3} |
    |---------------- - | --------------- | --------------- |
    | ${4:Item1.1} | - ${5:Item2.1} | ${6:Item3.1} |
    | ${7:Item1.2} | - ${8:Item2.2} | ${9:Item3.2} |
    | ${10:Item1.3} | - ${11:Item2.3} | ${12:Item3.3} |
    ${0}
    -
    5x3tableInsert 5x3 table - Insert table with 5 rows and 3 columns. First row is heading. - - | ${1:Column1} | ${2:Column2} | ${3:Column3} |
    |---------------- - | --------------- | --------------- |
    | ${4:Item1.1} | - ${5:Item2.1} | ${6:Item3.1} |
    | ${7:Item1.2} | - ${8:Item2.2} | ${9:Item3.2} |
    | ${10:Item1.3} | - ${11:Item2.3} | ${12:Item3.3} |
    | ${13:Item1.4} | - ${14:Item2.4} | ${15:Item3.4} |
    ${0}
    -
    -
    -

    Vue VSCode Snippets

    -
    -

    vue.json

    - Available in the following languages: vue. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    vbaseVue Single File ComponentBase for Vue File with SCSS - <template>
    - <div>

    - </div>
    </template>

    <script>
    - export default {
    - ${0}
    - }
    </script>

    <style lang="scss" - scoped>

    </style>
    -
    vbase-sassVue Single File Component with SASSBase for Vue File with PostCSS - <template>
    - <div>

    - </div>
    </template>

    <script>
    - export default {
    - ${0}
    - }
    </script>

    <style lang="sass" - scoped>

    </style>
    -
    vbase-lessVue Single File Component with LESSBase for Vue File with PostCSS - <template>
    - <div>

    - </div>
    </template>

    <script>
    - export default {
    - ${0}
    - }
    </script>

    <style lang="less" - scoped>

    </style>
    -
    vbase-pcssVue Single File Component with postcssBase for Vue File with PostCSS - <template>
    - <div>

    - </div>
    </template>

    <script>
    - export default {
    - ${0}
    - }
    </script>

    <style lang="postcss" - scoped>

    </style>
    -
    vbase-cssVue Single File Component with CssBase for Vue File with CSS - <template>
    - <div>

    - </div>
    </template>

    <script>
    - export default {
    - ${0}
    - }
    </script>

    <style scoped>

    </style>
    -
    vbase-stylVue Single File Component with StylusBase for Vue File with Stylus - <template>
    - <div>

    - </div>
    </template>

    <script>
    - export default {
    - ${0}
    - }
    </script>

    <style lang="stylus" - scoped>

    </style>
    -
    vbase-tsVue Single File Component with TypescriptBase for Vue File with Typescript - <template>
    - <div>

    - </div>
    </template>

    <script - lang="ts">
    - import Vue from 'vue'

    - export default Vue.extend({
    - ${0}
    - })
    </script>

    <style scoped>

    </style>
    -
    vbase-nsVue Single File Component with No StyleBase for Vue File with no styles - <template>
    - <div>

    - </div>
    </template>

    <script>
    - export default {
    - ${0}
    - }
    </script>
    -
    vbase-3Vue Single File Component Composition APIBase for Vue File Composition API with SCSS - <template>
    - <div>

    - </div>
    </template>

    <script>
    export - default {
    - setup () {
    - ${0}

    - return {}
    - }
    }
    </script>

    <style lang="scss" - scoped>

    </style>
    -
    vbase-3-reactiveVue Single File Component Composition API ReactiveBase for Vue File Composition API with SCSS - <template>
    - <div>

    - </div>
    </template>

    <script>
    import - { reactive, toRefs } from '@vue/composition-api'

    export - default {
    - setup () {
    - const state = reactive({
    - ${0:count}: ${1:0},
    - })
    -
    - return {
    - ...toRefs(state),
    - }
    - }
    }
    </script>

    <style lang="scss" - scoped>

    </style>
    -
    vbase-3-tsVue Single File Component Composition API with TypescriptBase for Vue File Composition API - Typescript - <template>
    - <div>

    - </div>
    </template>

    <script - lang="ts">
    import { defineComponent } from 'vue'

    export - default defineComponent({
    - setup () {
    - ${0}
    - return {}
    - }
    })
    </script>

    <style - scoped>

    </style>
    -
    vbase-ts-class - Vue Single File Component with Class based Typescript format - Base for Vue File with Class based Typescript format - <template>
    - <div>

    - </div>
    </template>

    <script - lang="ts">
    - import { Component, Vue } from 'vue-property-decorator';

    - @Component
    - export default class ${0} extends Vue {
    -
    - }
    </script>

    <style scoped>

    </style>
    -
    -
    -
    -

    vue-pug.json

    - Available in the following languages: jade. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    vforVue v-forvfor statement - ${1:div}(v-for="${2:item} in ${2:item}s" - :key="${2:item}.id")
    - | {{ ${2:item} }}
    -
    vmodelVue v-model Directivev-model directive - input(v-model="${1:data}" type="text")
    -
    vmodel-numVue v-model Number Directivev-model directive number input - input(v-model.number="${1:numData}" type="number" - step="1")
    -
    vonVue v-on Shortcut Directivev-on click handler with arguments - @click="${1:handler}(${2:arg}, $event)"
    -
    vel-propsVue Component with Props Bindingcomponent element with props - ${1:component}(:${1:propName}="${0}")
    -
    vsrcVue Image Source Bindingimage source binding - img(:src="'/path/to/images/' + ${1:fileName}" - alt="${2:altText}")
    -
    vstyleVue Style Bindingvue inline style binding - ${1:div}(:style="{ fontSize: ${2:data} + 'px' }")
    -
    vstyle-objVue Style Binding Objectvue inline style binding, objects - ${1:div}(:style="[${2:styleObjectA}, ${3:styleObjectB]}")
    -
    vclassVue Class Bindingvue class binding - ${1:div}(:class="{ ${2:className}: ${3:data} }")
    -
    vclass-objVue Class Binding Objectvue class binding - ${1:div}(:class="[${2:classNameA}, ${3:classNameB}]")
    -
    vclass-obj-multVue Multiple Conditional Class Bindingsvue multiple conditional class bindings - ${1:div}(:class="[${2:classNameA}, {${3:classNameB} : - ${4:condition}}]")
    -
    vanimVue Transition Component with JavaScript Hookstransition component js hooks - transition(
    - mode="out-in"
    - @before-enter="beforeEnter"
    - @enter="enter"

    - @before-leave="beforeLeave"
    - @leave="leave"
    - :css="false"
    )
    -
    vnuxtlVue Nuxt Routing Linknuxt routing link - nuxt-link(to="/${1:page}") ${1:page}
    -
    -
    -
    -

    vue-template.json

    - Available in the following languages: html, vue-html. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    vforVue v-forvfor statement - <${1:div} v-for="${2:item} in ${2:item}s" - :key="${2:item}.id">
    - {{ ${2:item} }}
    </${1:div}>
    -
    vmodelVue v-model Directivev-model directive - <input v-model="${1:data}" type="text" />
    -
    vmodel-numVue v-model Number Directivev-model directive number input - <input v-model.number="${1:numData}" type="number" - step="1" />
    -
    vonVue v-on Shortcut Directivev-on click handler with arguments - @click="${1:handler}(${2:arg}, $event)"
    -
    vel-propsVue Component with Props Bindingcomponent element with props - <${1:component} - :${1:propName}="${0}"></${1:component}>
    -
    vslot-namedVue Named Slotnamed slot - <template - v-slot:${0:name}>${1:defaultcontent}</template>
    -
    vsrcVue Image Source Bindingimage source binding - <img :src="'/path/to/images/' + ${1:fileName}" - alt="${2:altText}"/>
    -
    vstyleVue Style Bindingvue inline style binding - <${1:div} :style="{ fontSize: ${2:data} + 'px' - }"></${1:div}>
    -
    vstyle-objVue Style Binding Objectvue inline style binding, objects - <${1:div} :style="[${2:styleObjectA}, - ${3:styleObjectB]}"></${1:div}>
    -
    vclassVue Class Bindingvue class binding - <${1:div} :class="{ ${2:className}: ${3:data} - }"></${1:div}>
    -
    vclass-objVue Class Binding Objectvue class binding - <${1:div} :class="[${2:classNameA}, - ${3:classNameB}]"></${1:div}>
    -
    vclass-obj-multVue Multiple Conditional Class Bindingsvue multiple conditional class bindings - <${1:div} :class="[${2:classNameA}, {${3:classNameB} : - ${4:condition}}]"></${1:div}>
    -
    vemit-childVue Emit from ChildVue Emit from Child Component - @change="$$emit('change', $$event.target.value)"
    -
    vemit-parentVue Emit to ParentVue Emit to Parent Component - @change="${1:foo} = $$event"
    -
    vanimVue Transition Component with JavaScript Hookstransition component js hooks - <transition
    - mode="out-in"
    - @before-enter="beforeEnter"
    - @enter="enter"

    - @before-leave="beforeLeave"
    - @leave="leave"
    - :css="false">

    </transition>
    -
    vnuxtlVue Nuxt Routing Linknuxt routing link - <nuxt-link - to="/${1:page}">${1:page}</nuxt-link>
    -
    vroutenameVue Named Routing LinkNamed routing link - <router-link :to="{name: - '${1:name}'}">${2:LinkTitle}</router-link>
    -
    vroutenameparamVue Named Routing Link with ParamsNamed routing link w/ params - <router-link :to="{name: '${1:name}', params:{${2:id}: - '${3:value}'} }">${4:LinkTitle}</router-link>
    -
    vroutepathVue Path Routing LinkPath routing link - <router-link - to="${1:path}">${2:LinkTitle}</router-link>
    -
    -
    -
    -

    vue-script.json

    - Available in the following languages: javascript, typescript. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    vdataVue DataVue Component Data - data() {
    - return {
    - ${1:key}: ${2:value}
    - }
    },
    -
    vmethodVue Methodsvue method - methods: {
    - ${1:name}() {
    - ${0}
    - }
    },
    -
    vcomputedVue Computedcomputed value - computed: {
    - ${1:name}() {
    - return this.${2:data} ${0}
    - }
    },
    -
    vbeforecreateVue Lifecycle beforeCreatebeforeCreate lifecycle method - beforeCreate () {
    - ${0};
    },
    -
    vcreatedVue Lifecycle createdcreated lifecycle method - created () {
    - ${0};
    },
    -
    vbeforemountVue Lifecycle beforeMountbeforeMount lifecycle method - beforeMount () {
    - ${0};
    },
    -
    vmountedVue Lifecycle mountedmounted lifecycle method - mounted () {
    - ${0};
    },
    -
    vbeforeupdateVue Lifecycle beforeUpdatebeforeUpdate lifecycle method - beforeUpdate () {
    - ${0};
    },
    -
    vupdatedVue Lifecycle updatedupdated lifecycle method - updated () {
    - ${0};
    },
    -
    vbeforedestroyVue Lifecycle beforeDestroybeforeDestroy lifecycle method - beforeDestroy () {
    - ${0};
    },
    -
    vdestroyedVue Lifecycle destroyeddestroyed lifecycle method - destroyed () {
    - ${0};
    },
    -
    vwatcherVue Watchersvue watcher - watch: {
    - ${1:data}(${2:newValue}, ${3:oldValue}) {
    - ${0}
    - }
    },
    -
    vwatcher-optionsVue Watchers with Optionsvue watcher with options - watch: {
    - ${1:data}: {
    - immediate: ${2:true},
    - deep: ${3:true},
    - handler(${4:newValue}, ${5:oldValue}) {
    - ${0}
    - }
    - }
    },
    -
    vpropsVue Props with DefaultVue Props with Default - props: {
    - ${1:propName}: {
    - type: ${2:Number},
    - default: ${0}
    - },
    },
    -
    vimportVue Import FileImport one component into another - import ${1:New} from '@/components/${1:New}.vue';
    -
    vcomponentsVue Import into the Component - Import one component into another, within export statement - - components: {
    - ${1:New},
    },
    -
    vimport-exportVue Import Exportimport a component and include it in export default - import ${1:Name} from '@/components/${1:Name}.vue';

    export - default {
    - components: {
    - ${1:Name}
    - },
    };
    -
    vimport-dynamicVue Import Component DynamicallyImport component that should be lazy loaded - ${1:New} = () => import('@/components/${1:New}.vue')
    -
    vmapstateVue MapStatemap getters inside a vue component - import { mapState } from 'vuex';

    export default - {
    - computed: {
    - ...mapState([
    - ${1:'nameOfState'},
    - ])
    - },
    };
    -
    vmapgettersVue MapGettersmapgetters inside a vue component - import { mapGetters } from 'vuex';

    export default - {
    - computed: {
    - ...mapGetters([
    - ${1:'nameOfGetter'},
    - ])
    - },
    };
    -
    vmapmutationsVue MapMutationsmapmutations inside a vue component - import { mapMutations } from 'vuex';

    export - default {
    - methods: {
    - ...mapMutations([
    - ${1:'nameOfMutation'}, //also supports payload - `this.nameOfMutation(amount)`
    - ])
    - },
    };
    -
    vmapactionsVue MapActionsmapactions inside a vue component - import { mapActions } from 'vuex';

    export default - {
    - methods: {
    - ...mapActions([
    - ${1:'nameOfAction'}, //also supports payload - `this.nameOfAction(amount)`
    - ])
    - },
    };
    -
    vfilterVue Filtervue filter - filters: {
    - ${1:fnName}: function(${2:value}) {
    - return ${2:value}${0};
    - }
    }
    -
    vmixinVue Mixinvue mixin - const ${1:mixinName} = {
    - mounted() {
    - console.log('hello from mixin!');
    - },
    };
    -
    vmixin-useVue Use Mixinvue use mixin - mixins: [${1:mixinName}],
    -
    vc-directVue Custom Directivevue custom directive - Vue.directive('${1:directiveName}', {
    - bind(el, binding, vnode) {
    - el.style.${2:arg} = binding.value.${2:arg};
    - }
    });
    -
    vimport-libVue Import Libraryimport a library - import { ${1:libName} } from '${1:libName}';
    -
    vimport-gsapVue Import GSAPimport gsap library - import gsap from 'gsap';
    -
    vanimhook-jsVue Transition Methods with JavaScript Hookstransition component js hooks - beforeEnter(el) {
    - console.log('beforeEnter');
    },
    enter(el, done) {
    - console.log('enter');
    - done();
    },
    beforeLeave(el) {
    - console.log('beforeLeave');
    },
    leave(el, done) {
    - console.log('leave');
    - done();
    },
    -
    vcommitVue Commit Vuex Store in Methodscommit to vuex store in methods for mutation - ${1:mutationName}() {
    - this.\$store.commit('${1:mutationName}', ${2:payload});
    }
    -
    vdispatchVue Dispatch Vuex Store in Methodsdispatch to vuex store in methods for action - ${1:actionName}() {
    - this.\$store.dispatch('${1:actionName}', ${2:payload});
    }
    -
    vtestUnit Testunit test component - import Vue from 'vue';
    import ${1:HelloWorld} from - './components/${1:HelloWorld}';

    describe('${1:HelloWorld}.vue', - () => {
    - it('${2:should render correct contents}', () => {
    - const Constructor = Vue.extend(${1:HelloWorld});
    - const vm = new Constructor().$mount();
    - expect(vm.$el.querySelector('.hello h1').textContent)
    - .to.equal(${3:'Welcome to Your Vue.js App'});
    - });
    });
    -
    vconfigVue.config.js Importvue.config.js - module.exports = {
    - css: {
    - loaderOptions: {
    - ${1:sass}: {
    - data: `${2:@import '@/styles/_variables.scss';}`
    - }
    - }
    - }
    }
    -
    v3reactiveVue Composition API - ReactiveVue Composition api - reactive - const ${1:name} = reactive({
    - ${2:count}: ${3:0}
    })
    -
    v3computedVue Composition API - ComputedVue Composition api - computed - const ${1:name} = computed(() => {
    - return ${2}
    })
    -
    v3watchVue Composition API - watch - single sourceVue Composition api - watcher single source - watch(() => ${1:foo}, (newValue, oldValue) => {
    - ${2}
    })
    -
    v3watch-arrayVue Composition API - watch - arrayVue Composition api - watch as array - watch([${1:foo}, ${2:bar}], ([new${1}, new${2}], [prev${1}, - prev${2}]) => {
    - ${3}
    })
    -
    v3watcheffectVue Composition API - watchEffectVue Composition api - watchEffect - watchEffect(() => {
    - ${1}
    })
    -
    v3refVue Composition API - Vue refVue Ref - const ${1:name} = ref(${2:initialValue})
    -
    v3onmountedVue Lifecycle Hooks - onMountedVue Mounted Lifecycle hook - onMounted(() => {${1}})
    -
    v3onbeforemountVue Lifecycle Hooks - onBeforeMountVue onBeforeMount Lifecycle hook - onBeforeMount(() => {${1}})
    -
    v3onbeforeupdateVue Lifecycle Hooks - onBeforeUpdateVue onBeforeUpdate Lifecycle hook - onBeforeUpdate(() => {${1}})
    -
    v3onupdatedVue Lifecycle Hooks - onUpdatedVue onUpdated Lifecycle hook - onUpdated(() => {${1}})
    -
    v3onerrorcapturedVue Lifecycle Hooks - onErrorCapturedVue onErrorCaptured Lifecycle hook - onErrorCaptured(() => {${1}})
    -
    v3onunmountedVue Lifecycle Hooks - onUnmounted(destroyed) Vue onUnmounted Lifecycle hook - onUnmounted(() => {${1}})
    -
    v3onbeforeunmountVue Lifecycle Hooks - onBeforeUnmount(beforeDestroy) Vue onBeforeUnmount Lifecycle hook - onBeforeUnmount(() => {${1}})
    -
    vpluginPlugin importImport a plugin to main.js or plugins file - import Vue from 'vue'
    import ${1:VueCompositionApi} from - '${2:@vue/composition-api}'

    Vue.use(${1:VueCompositionApi})
    -
    v3reactive-setupVue Composition API Reactive ScriptVue Composition API Script with Reactive - import { reactive, toRefs } from '@vue/composition-api'

    export - default {
    - setup () {
    - const state = reactive({
    - ${0:count}: ${1:0},
    - })
    -
    - return {
    - ...toRefs(state),
    - }
    - }
    }
    -
    v3useinoptionsUse Composition API within Options APIUse Composition API within Options API - import { ${0:component} } from - '@/composables/${0:component}.js'

    export default - {
    - setup () {
    - const { ${1:name} } = ${0:component}()
    -
    - return {
    - ${1:name}
    - }
    - }
    }
    -
    -
    -
    -

    vue-script-vuex.json

    - Available in the following languages: javascript, typescript. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    vstoreVuex StoreBase for Vuex store - import Vue from 'vue';
    import Vuex from 'vuex';

    Vue.use(Vuex);

    export - const store = new Vuex.Store({
    - state: {
    - ${1:key}: ${2:value}
    - }
    });
    -
    vgetterVuex Gettersvuex getter - getters: {
    - ${1:value}: state => {
    - return state.${1:value};
    - }
    }
    -
    vmutationVuex Mutationvuex mutation - mutations: {
    - ${1:updateValue}(state, ${3:payload}) {
    - state.${2:value} = ${3:payload};
    - }
    }
    -
    vactionVuex Actionvuex action - actions: {
    - ${1:updateValue}({commit}, ${2:payload}) {
    - commit('${1:updateValue}', ${2:payload});
    - }
    }
    -
    vstore-importVue Import Vuex Storeimport vuex store into main.js - import { store } from './store/index';
    -
    vmoduleVuex Modulevuex module - export default {
    - state: {
    - value: 'my value'
    - },
    - getters: {
    - value: state => {
    - return state.value;
    - }
    - },
    - mutations: {
    - updateValue(state, payload) {
    - state.value = payload;
    - }
    - },
    - actions: {
    - updateValue({commit}, payload) {
    - commit('updateValue', payload);
    - }
    - }
    };
    -
    vstore2Vuex Store 2vuex store 2 - export const state = () => ({
    - value: 'myvalue'
    })

    export const getters = - {
    - getterValue: state => {
    - return state.value
    - }
    }

    export const mutations = {
    - updateValue: (state, payload) => {
    - state.value = payload
    - }
    }

    export const actions = {
    - updateActionValue({ commit }) {
    - commit('updateValue', payload)
    - }
    }
    -
    -
    -
    -

    vue-script-router.json

    - Available in the following languages: javascript, typescript. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    vrouterVue RouterBase for Vue Router - import Vue from 'vue';
    import VueRouter from - 'vue-router';

    Vue.use(VueRouter);

    export - const router = new VueRouter({
    - base: '/',
    - mode: 'history',
    - routes: [
    - { path: '/path', component: component }
    - ]
    });
    -
    vscrollbehaviorVue Router scrollBehaviorVue Router scrollBehavior - scrollBehavior(to, from, savedPosition) {
    - if(savedPosition) {
    - return savedPosition;
    - } else {
    - return { x: 0, y: 0 };
    - }
    },
    -
    vbeforeeachVue Router beforeEachVue Router global guards beforeEach - router.beforeEach((to, from, next) => {
    - ${1:next();}
    });
    -
    vbeforeresolveVue Router beforeResolveVue Router global guards beforeResolve - router.beforeResolve((to, from, next) => {
    - ${1:next();}
    });
    -
    vaftereachVue Router afterEachVue Router global guards afterEach - router.afterEach((to, from) => {
    -
    });
    -
    vbeforeenterVue Router beforeEnterVue Router per-route guard beforeEnter - beforeEnter(to, from, next) {
    - ${1:next();}
    },
    -
    vbeforerouteenterVue Router beforeRouteEnterVue Router component guards beforeRouteEnter - beforeRouteEnter(to, from, next) {
    - next(vm => {${1:}});
    },
    -
    vbeforerouteupdateVue Router beforeRouteUpdateVue Router component guards beforeRouteUpdate - beforeRouteUpdate(to, from, next) {
    - ${1:next();}
    },
    -
    vbeforerouteleaveVue Router beforeRouteLeaveVue Router component guards beforeRouteLeave - beforeRouteLeave(to, from, next) {
    - ${1:next();}
    },
    -
    vroute-namedVue Router RouteVue Router route with per route code-splitting - {
    - path: '${1:pathName}',
    - name: '${2:routeName}',
    - component: () => import('./${3:pathToComponent}'),
    },
    -
    -
    -
    -

    nuxt-config.json

    - Available in the following languages: javascript, typescript. - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    nfontNuxt Fontlink to include fonts in a nuxt project, in nuxt-config - { rel: 'stylesheet', href: - '${1:https://fonts.googleapis.com/css?family=Montserrat:600|Rufina:700}' - }
    -
    ncssNuxt Use CSS Filelink to css assets such as normalize - css: ['assets/${1:normalize.css}'],
    -
    -
    -
    -

    nuxt-script.json

    - Available in the following languages: javascript. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    nasyncdataNuxt AsyncNuxt asyncData - async asyncData ({ ${1:params} }) {
    - const { data } = await fetch(`${2:endpoint}`).then(res => - res.json())
    - return { ${3:key}:${4:value} }
    },
    -
    nfetchNuxt FetchNuxt Fetch - async fetch ({ store, ${1:params} }) {
    - let { data } = await fetch('${2:endpoint}').then(res => - res.json())
    - store.commit('${3:MUTATION_TYPE}', data)
    },
    -
    nparamNuxt Route ParamsNuxt Route Params - this.$route.params.${1:id}
    -
    nheadNuxt HeadNuxt Head - head () {
    - return {
    - title: ${1:'Page Title'},
    - meta: [
    - // hid is used as unique identifier. Do not use `vmid` for it - as it will not work
    - { hid: 'description', name: 'description', content: ${2:'My - custom description'} }
    - ]
    - }
    },
    -
    -
    -
    -
    -

    VS Code Snippets

    -
    -

    Batchfile

    - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    #regionRegion StartFolding Region Start - ::#region
    -
    #endregionRegion EndFolding Region End - ::#endregion
    -
    -
    -
    -

    Coffeescript

    - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    #regionRegion StartFolding Region Start - #region
    -
    #endregionRegion EndFolding Region End - #endregion
    -
    -
    -
    -

    C

    - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    #regionRegion StartFolding Region Start - #pragma region $0
    -
    #endregionRegion EndFolding Region End - #pragma endregion
    -
    -
    -
    -

    CPP

    - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    #regionRegion StartFolding Region Start - #pragma region $0
    -
    #endregionRegion EndFolding Region End - #pragma endregion
    -
    -
    -
    -

    Csharp

    - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    #regionRegion StartFolding Region Start - #region $0
    -
    #endregionRegion EndFolding Region End - #endregion
    -
    -
    -
    -

    Fsharp

    - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    #regionRegion StartFolding Region Start - //#region $0
    -
    #endregionRegion EndFolding Region End - //#endregion
    -
    -
    -
    -

    Groovy

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    replacereplace(dir: …, includes: …, token: …, value: …)Replace(...) - replace(dir:"${1:dirName}", includes:"${2:*.*}", - token:"${3:tokenName}", value:"\${${4:value}}")$0
    -
    docDoc BlockDoc block comment - /**
    - * $0
    - */
    -
    keykey: "value" (Hash Pair) - ${1:key}: ${2:"${3:value}"}
    -
    threadThread.start { … }Thread.start { ... } - Thread.start {
    - $0
    }
    -
    threadThread.startDaemon { … }Thread.startDaemon { ... } - Thread.startDaemon {
    - $0
    }
    -
    casecase … breakcase ... break - case ${1:CASE_NAME}:
    - $2
    break$0
    -
    instanceinstance … (Singleton)Singleton instance + Getter - private static $1 instance

    static $1 - getInstance(${2:args}) {
    - if (!instance) instance = new $1(${2:args})
    - return instance
    }
    -
    tcclass … extends GroovyTestCase { … }GroovyTestCase class - class $1 extends GroovyTestCase {

    - $0
    }
    -
    copycopy(file: …, tofile: …)Copy file - copy(file:"${1:sourceFile}", tofile:"${2:targetFile}")
    -
    copycopy(todir: …) { fileset(dir: …) { include … exclude }Copy fileset todir w/ include/exclude - copy(todir:"${1:targetDir}") {
    - fileset(dir:"${2:sourceDir}") {
    - include(name:"${3:includeName}")
    - exclude(name:"${4:excludeName}")
    - }
    }
    -
    copycopy(todir: …) { fileset:dir …) }Copy fileset todir - copy(todir:"${1:targetDir}") {
    - fileset(dir:"${2:sourceDir}")
    }
    -
    cvclosure = { … }Closure block - def ${1:closureName} = { ${2:args} ->
    - $0
    }
    -
    forinfor(… in …) { … }For-loop - for (${1:element} in ${2:collection}) {
    - $0
    }
    -
    mkdirmkdir(dir: …)mkdir - mkdir(dir:"${1:dirName}")
    -
    pprintprint - print $0
    -
    plprintlnprintln - println $0
    -
    runarunAfter() { … }runAfter() { ... } - runAfter(${1:delay}) {
    - $0
    }
    -
    setupsetUp() { … }setup() { ... } - void setUp() {
    - $0
    }
    -
    sleepsleep(secs) { … // on interrupt do }sleep with interrupt - sleep(${1:secs}) {
    - ${2:// on interrupt do}
    }
    -
    sleepsleep(secs)sleep - sleep(${1:secs})
    -
    sortsort { … }sort - sort {
    - $0
    }
    -
    mainstatic main() { … }main method - static main(args) {
    - $0
    }
    -
    switchswitch … caseSwitch-Case block - switch(${1:value}) {
    - case ${2:CASE}:
    - $3
    - break$0
    }
    -
    switchswitch … case … defaultSwitch-Case-Default block - switch(${1:value}) {
    - case ${3:CASE}:
    - $4
    - break$0
    - default:
    - $2
    - break
    }
    -
    teartearDown() { … }tearDown() { ... } - void tearDown() {
    - $0
    }
    -
    ttest()test method - void test$1() {
    - $0
    }
    -
    vvarvar - ${1:def} ${2:var}${3: = ${0:null}}
    -
    -
    -
    -

    Java

    - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    #regionRegion StartFolding Region Start - //#region
    -
    #endregionRegion EndFolding Region End - //#endregion
    -
    -
    -
    -

    Javascript

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    definedefine moduledefine module - define([
    - 'require',
    - '${1:dependency}'
    ], function(require, ${2:factory}) {
    - 'use strict';
    - $0
    });
    -
    forFor LoopFor Loop - for (let ${1:index} = 0; ${1:index} < ${2:array}.length; - ${1:index}++) {
    - const ${3:element} = ${2:array}[${1:index}];
    - $0
    }
    -
    foreachFor-Each LoopFor-Each Loop - ${1:array}.forEach(${2:element} => {
    - $0
    });
    -
    forinFor-In LoopFor-In Loop - for (const ${1:key} in ${2:object}) {
    - if (${2:object}.hasOwnProperty(${1:key})) {
    - const ${3:element} = ${2:object}[${1:key}];
    - $0
    - }
    }
    -
    forofFor-Of LoopFor-Of Loop - for (const ${1:iterator} of ${2:object}) {
    - $0
    }
    -
    functionFunction StatementFunction Statement - function ${1:name}(${2:params}) {
    - $0
    }
    -
    ifIf StatementIf Statement - if (${1:condition}) {
    - $0
    }
    -
    ifelseIf-Else StatementIf-Else Statement - if (${1:condition}) {
    - $0
    } else {
    -
    }
    -
    newNew StatementNew Statement - const ${1:name} = new ${2:type}(${3:arguments});$0
    -
    switchSwitch StatementSwitch Statement - switch (${1:key}) {
    - case ${2:value}:
    - $0
    - break;

    - default:
    - break;
    }
    -
    whileWhile StatementWhile Statement - while (${1:condition}) {
    - $0
    }
    -
    dowhileDo-While StatementDo-While Statement - do {
    - $0
    } while (${1:condition});
    -
    trycatchTry-Catch StatementTry-Catch Statement - try {
    - $0
    } catch (${1:error}) {
    -
    }
    -
    settimeoutSet Timeout FunctionSet Timeout Function - setTimeout(() => {
    - $0
    }, ${1:timeout});
    -
    setintervalSet Interval FunctionSet Interval Function - setInterval(() => {
    - $0
    }, ${1:interval});
    -
    import statementImport external module.Import external module. - import { $0 } from "${1:module}";
    -
    #regionRegion StartFolding Region Start - //#region $0
    -
    #endregionRegion EndFolding Region End - //#endregion
    -
    logLog to the consoleLog to the console - console.log($1);
    -
    warnLog warning to consoleLog warning to the console - console.warn($1);
    -
    errorLog error to consoleLog error to the console - console.error($1);
    -
    -
    -
    -

    Markdown

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    boldInsert bold textInsert bold text - **${1:${TM_SELECTED_TEXT}}**$0
    -
    italicInsert italic textInsert italic text - *${1:${TM_SELECTED_TEXT}}*$0
    -
    quoteInsert quoted textInsert quoted text - > ${1:${TM_SELECTED_TEXT}}
    -
    codeInsert codeInsert code - `${1:${TM_SELECTED_TEXT}}`$0
    -
    fenced codeblockInsert fenced code blockInsert fenced code block - ```${1:language}
    ${TM_SELECTED_TEXT}$0
    ```
    -
    headingInsert headingInsert heading - # ${1:${TM_SELECTED_TEXT}}
    -
    unordered listInsert unordered listInsert unordered list - - ${1:first}
    - ${2:second}
    - ${3:third}
    $0
    -
    ordered listInsert ordered listInsert ordered list - 1. ${1:first}
    2. ${2:second}
    3. ${3:third}
    $0
    -
    horizontal ruleInsert horizontal ruleInsert horizontal rule - ----------
    -
    linkInsert linkInsert link - [${TM_SELECTED_TEXT:${1:text}}](https://${2:link})$0
    -
    imageInsert imageInsert image - ![${TM_SELECTED_TEXT:${1:alt}}](https://${2:link})$0
    -
    -
    -
    -

    PHP

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    classclass …Class definition - class ${1:ClassName} ${2:extends ${3:AnotherClass}} - ${4:implements ${5:Interface}}
    {
    - $0
    }

    -
    doc_classPHPDoc class …Documented Class Declaration - /**
    - * ${6:undocumented class}
    - */
    class ${1:ClassName} ${2:extends ${3:AnotherClass}} - ${4:implements ${5:Interface}}
    {
    - $0
    }

    -
    confunction __construct - ${1:public} function __construct(${2:${3:Type} $${4:var}${5: - = ${6:null}}}) {
    - \$this->${4:var} = $${4:var};$0
    }
    -
    doc_vPHPDoc propertyDocumented Class Variable - /** @var ${1:Type} $${2:var} ${3:description} */
    ${4:protected} - $${2:var}${5: = ${6:null}};$0
    -
    doc_fPHPDoc function …Documented function - /**
    - * ${1:undocumented function summary}
    - *
    - * ${2:Undocumented function long description}
    - *
    ${3: * @param ${4:Type} $${5:var} ${6:Description}}
    ${7: - * @return ${8:type}}
    ${9: * @throws ${10:conditon}}
    - **/
    ${11:public }function - ${12:FunctionName}(${13:${14:${4:Type} }$${5:var}${15: = - ${16:null}}})
    {
    - ${0:# code...}
    }
    -
    paramPHPDoc param …Paramater documentation - * @param ${1:Type} ${2:var} ${3:Description}$0
    -
    funfunction …Function - ${1:public }function ${2:FunctionName}(${3:${4:${5:Type} - }$${6:var}${7: = ${8:null}}})
    {
    - ${0:# code...}
    }
    -
    traittrait …Trait - /**
    - * $1
    - */
    trait ${2:TraitName}
    {
    - $0
    }

    -
    defdefine(…, …)Definition - define('$1', ${2:'$3'});
    $0
    -
    dodo … while …Do-While loop - do {
    - ${0:# code...}
    } while (${1:$${2:a} <= ${3:10}});
    -
    whilewhile …While-loop - while (${1:$${2:a} <= ${3:10}}) {
    - ${0:# code...}
    }
    -
    ifif …If block - if (${1:condition}) {
    - ${0:# code...}
    }
    -
    ifelseif … else …If Else block - if (${1:condition}) {
    - ${2:# code...}
    } else {
    - ${3:# code...}
    }
    $0
    -
    if?$… = ( … ) ? … : …Ternary conditional assignment - $${1:retVal} = (${2:condition}) ? ${3:a} : ${4:b} ;
    -
    elseelse …Else block - else {
    - ${0:# code...}
    }
    -
    elseifelseif …Elseif block - elseif (${1:condition}) {
    - ${0:# code...}
    }
    -
    forfor …For-loop - for ($${1:i}=${2:0}; $${1:i} < $3; $${1:i}++) {
    - ${0:# code...}
    }
    -
    foreachforeach …Foreach loop - foreach ($${1:variable} as $${2:key} ${3:=> $${4:value}}) - {
    - ${0:# code...}
    }
    -
    array$… = array (…)Array initializer - $${1:arrayName} = array('$2' => $3${4:,} $0);
    -
    shorray$… = […]Array initializer - $${1:arrayName} = ['$2' => $3${4:,} $0];
    -
    keyval… => …Key-Value initializer - '$1' => $2${3:,} $0
    -
    switchswitch …Switch block - switch (\$${1:variable}) {
    - case '${2:value}':
    - ${3:# code...}
    - break;
    - $0
    - default:
    - ${4:# code...}
    - break;
    }
    -
    casecase …Case Block - case '${1:value}':
    - ${0:# code...}
    - break;
    -
    this$this->…$this->... - \$this->$0;
    -
    ethisecho $this->…Echo this - echo \$this->$0;
    -
    throwThrow ExceptionThrow exception - throw new $1Exception(${2:"${3:Error Processing - Request}"}${4:, ${5:1}});
    $0
    -
    #regionRegion StartFolding Region Start - #region
    -
    #endregionRegion EndFolding Region End - #endregion
    -
    tryTry Catch BlockTry catch block - try {
    - ${1://code...}
    } catch (${2:\Throwable} ${3:\$th}) {
    - ${4://throw \$th;}
    }
    -
    -
    -
    -

    Powershell

    - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    #regionRegion StartFolding Region Start - #region $0
    -
    #endregionRegion EndFolding Region End - #endregion
    -
    -
    -
    -

    Swift

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    printprintprint("...") - print("$1") $0
    -
    printvprint valueprint("\(...)") - print("\($1)") $0
    -
    whilewhilewhile statement - while ${1:condition} {
    - $0
    }
    -
    repeatrepeat-whilerepeat-while statement - repeat {
    - $0
    } while ${1:condition}
    -
    forforfor-in statement - for ${1:item} in ${2:collection} {
    - $0
    }
    -
    ififif statement - if ${1:condition} {
    - $0
    }
    -
    elifelse ifelse clause with a nested if statement - else if ${1:condition} {
    - $0
    }
    -
    elseelseelse clause - else {
    - $0
    }
    -
    ifletif letif statement with optional binding - if let ${1:value} = ${2:optional} {
    - $0
    }
    -
    guardguardguard statement - guard ${1:condition} else {
    - $0
    }
    -
    guardletguard letguard statement with optional binding - guard let ${1:value} = ${2:optional} else {
    - $0
    }
    -
    switchswitchswitch statement - switch ${1:value} {
    case ${2:pattern}:
    - $0
    default:
    -
    }
    -
    dododo statement - do {
    - $0
    } catch ${1:error} {
    - $2
    }
    -
    funcfuncfunction declaration - func ${1:name}(${2:parameters}) -> ${3:Type} {
    - $0
    }
    -
    structstructstruct declaration - struct ${1:Name} {

    - $0
    }
    -
    enumenumenum declaration - enum ${1:Name} {

    - case $0
    }
    -
    classclassclass declaration - class ${1:Name} {

    - $0
    }
    -
    protocolprotocolprotocol declaration - protocol ${1:Name} {

    - $0
    }
    -
    extensionextensionextension declaration - extension ${1:Type} {

    - $0
    }
    -
    -
    -
    -

    Typescript

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    ctorConstructorConstructor - /**
    - *
    - */
    constructor() {
    - super();
    - $0
    }
    -
    classClass DefinitionClass Definition - class ${1:name} {
    - constructor(${2:parameters}) {
    - $0
    - }
    }
    -
    public methodPublic Method DefinitionPublic Method Definition - /**
    - * ${1:name}
    - */
    public ${1:name}() {
    - $0
    }
    -
    private methodPrivate Method DefinitionPrivate Method Definition - private ${1:name}() {
    - $0
    }
    -
    import statementImport external module.Import external module. - import { $0 } from "${1:module}";
    -
    getProperty getterProperty getter -
    public get ${1:value}() : ${2:string} {
    - ${3:return $0}
    }

    -
    logLog to the consoleLog to the console - console.log($1);
    $0
    -
    warnLog warning to consoleLog warning to the console - console.warn($1);
    $0
    -
    errorLog error to consoleLog error to the console - console.error($1);
    $0
    -
    propDefine a full propertyDefine a full property -
    private _${1:value} : ${2:string};
    public get - ${1:value}() : ${2:string} {
    - return this._${1:value};
    }
    public set ${1:value}(v : - ${2:string}) {
    - this._${1:value} = v;
    }

    -
    refTriple-slash referenceTriple-slash reference - /// <reference path="$1" />
    $0
    -
    setProperty setterProperty setter -
    public set ${1:value}(v : ${2:string}) {
    - this.$3 = v;
    }

    -
    throwThrow ExceptionThrow Exception - throw new Error("$1");
    $0
    -
    forFor LoopFor Loop - for (let ${1:index} = 0; ${1:index} < ${2:array}.length; - ${1:index}++) {
    - const ${3:element} = ${2:array}[${1:index}];
    - $0
    }
    -
    foreach =>For-Each Loop using =>For-Each Loop using => - ${1:array}.forEach(${2:element} => {
    - $0
    });
    -
    forinFor-In LoopFor-In Loop - for (const ${1:key} in ${2:object}) {
    - if (Object.prototype.hasOwnProperty.call(${2:object}, - ${1:key})) {
    - const ${3:element} = ${2:object}[${1:key}];
    - $0
    - }
    }
    -
    forofFor-Of LoopFor-Of Loop - for (const ${1:iterator} of ${2:object}) {
    - $0
    }
    -
    forawaitofFor-Await-Of LoopFor-Await-Of Loop - for await (const ${1:iterator} of ${2:object}) {
    - $0
    }
    -
    functionFunction StatementFunction Statement - function ${1:name}(${2:params}:${3:type}) {
    - $0
    }
    -
    ifIf StatementIf Statement - if (${1:condition}) {
    - $0
    }
    -
    ifelseIf-Else StatementIf-Else Statement - if (${1:condition}) {
    - $0
    } else {
    -
    }
    -
    newNew StatementNew Statement - const ${1:name} = new ${2:type}(${3:arguments});$0
    -
    switchSwitch StatementSwitch Statement - switch (${1:key}) {
    - case ${2:value}:
    - $0
    - break;

    - default:
    - break;
    }
    -
    whileWhile StatementWhile Statement - while (${1:condition}) {
    - $0
    }
    -
    dowhileDo-While StatementDo-While Statement - do {
    - $0
    } while (${1:condition});
    -
    trycatchTry-Catch StatementTry-Catch Statement - try {
    - $0
    } catch (${1:error}) {
    -
    }
    -
    settimeoutSet Timeout FunctionSet Timeout Function - setTimeout(() => {
    - $0
    }, ${1:timeout});
    -
    #regionRegion StartFolding Region Start - //#region $0
    -
    #endregionRegion EndFolding Region End - //#endregion
    -
    -
    -
    -

    VB

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    forFor Next LoopFor Next Loop - For ${1:index} As ${2:ObjectType} = ${3:lower} To - ${4:Upper}
    - $0
    Next ${1:index}
    -
    foreFor Each...NextFor Each...Next - For Each ${1:Variable} As ${2:ObjectType} In - ${3:Collection}
    - $0
    Next
    -
    foriFor i...Next iFor i...Next i - For i As ${1:Integer} = ${2:Lower} To ${3:Upper}
    - $0
    Next i
    -
    forjFor j...Next jFor j...Next j - For j As ${1:Integer} = ${2:Lower} To ${3:Upper}
    - $0
    Next j
    -
    pfPublic Function...Public Function... - Public Function ${1:FunctionName}(${2:ParameterList}) As - ${3:ReturnType}
    - Try
    - $0
    - Catch ex As Exception
    - End Try
    - Return ${3:ReturnValue}
    End Function
    -
    psPublic Sub ...Public Sub ... - Public Sub ${1:ProcedureName}(${2:ParameterList})
    - Try
    - $0
    - Catch ex As Exception
    - End Try
    End Sub
    -
    whileWhile ... End WhileWhile ... End While - While ${1:Boolean}
    - $0
    End While
    -
    #RegionRegion StartFolding Region Start - #Region $0
    -
    #End RegionRegion EndFolding Region End - #End Region
    -
    -
    -
    - - Go to top - - - - - - diff --git a/test/view-dark.html b/test/view-dark.html deleted file mode 100644 index dbde37e..0000000 --- a/test/view-dark.html +++ /dev/null @@ -1,5261 +0,0 @@ - - - - - -

    Snippets Ranger

    -
    -

    Table of Contents

    - -
    -
    -

    User Snippets

    -
    -

    Markdown

    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    testtest - [
    ${CLIPBOARD/^(.+)$/'$1',/gm}
    ]
    -
    upUpper the second mirrored tab stop - ${1:title}
    ${1/(.*)/${1:/upcase}/}
    ${1/(.*)/${1:/upcase}/}
    $0
    -
    -
    -
    -
    -

    Extension Snippets

    -

    markdownlint

    -
    -

    snippets.json

    -

    Available in the following languages:

    -
      -
    • markdown
    • -
    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    markdownlint-disableinsertMarkdownLintDisableComment - Disables one or more rules by name (MD013), alias (line-length), - or tag (whitespace). Multiple rules are space-delimited (MD018 - MD019). If no rules are specified, all rules are disabled. Takes - effect starting with the line the comment is on. - - <!-- markdownlint-disable ${1:MD000 }-->
    -
    markdownlint-enableinsertMarkdownLintEnableComment - Enables one or more rules by name (MD013), alias (line-length), - or tag (whitespace). Multiple rules are space-delimited (MD018 - MD019). If no rules are specified, all rules are enabled. Takes - effect starting with the line the comment is on. - - <!-- markdownlint-enable ${1:MD000 }-->
    -
    markdownlint-disable-fileinsertMarkdownLintDisableFileComment - Disables one or more rules by name (MD013), alias (line-length), - or tag (whitespace). Multiple rules are space-delimited (MD018 - MD019). If no rules are specified, all rules are disabled. - Applies to the entire file. - - <!-- markdownlint-disable-file ${1:MD000 }-->
    -
    markdownlint-enable-fileinsertMarkdownLintEnableFileComment - Enables one or more rules by name (MD013), alias (line-length), - or tag (whitespace). Multiple rules are space-delimited (MD018 - MD019). If no rules are specified, all rules are enabled. - Applies to the entire file. - - <!-- markdownlint-enable-file ${1:MD000 }-->
    -
    markdownlint-captureinsertMarkdownLintCaptureComment - Captures the current rule configuration. Takes effect starting - with the line the comment is on. - - <!-- markdownlint-capture -->
    -
    markdownlint-restoreinsertMarkdownLintRestoreComment - Restores the most recently captured rule configuration. Defaults - to the document's initial configuration. Takes effect starting - with the line the comment is on. - - <!-- markdownlint-restore -->
    -
    markdownlint-configure-fileinsertMarkdownLintConfigureFileComment - Configures one or more rules by name (MD013), alias - (line-length), or tag (whitespace) using the same JSON format as - the "markdownlint.config" object. Applies to the entire file. - - <!-- markdownlint-configure-file { ${1:"MD013": { - "line_length": 100 \}} } -->
    -
    -
    -

    Markdown Snippets

    -
    -

    snippets.code-snippets

    -

    Available in the following languages:

    -
      -
    • markdown
    • -
    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    taskInsert task listInsert task list - - [${1| ,x|}] ${2:text}
    ${0}
    -
    task2Insert task list 2Insert task list with 2 tasks - - [${1| ,x|}] ${2:text}
    - [${3| ,x|}] ${4:text}
    ${0}
    -
    task3Insert task list 3Insert task list with 3 tasks - - [${1| ,x|}] ${2:text}
    - [${3| ,x|}] ${4:text}
    - - [${5| ,x|}] ${6:text}
    ${0}
    -
    task4Insert task list 4Insert task list with 4 tasks - - [${1| ,x|}] ${2:text}
    - [${3| ,x|}] ${4:text}
    - - [${5| ,x|}] ${6:text}
    - [${7| ,x|}] ${8:text}
    ${0}
    -
    task5Insert task list 5Insert task list with 5 tasks - - [${1| ,x|}] ${2:text}
    - [${3| ,x|}] ${4:text}
    - - [${5| ,x|}] ${6:text}
    - [${7| ,x|}] ${8:text}
    - - [${9| ,x|}] ${10:text}
    ${0}
    -
    tableInsert table - Insert table with 2 rows and 3 columns. First row is heading. - - | ${1:Column1} | ${2:Column2} | ${3:Column3} |
    |-------------- - | -------------- | -------------- |
    | ${4:Item1} | - ${5:Item1} | ${6:Item1} |
    ${0}
    -
    2x1tableInsert 2x1 table - Insert table with 2 rows and 1 column. First row is heading. - - | ${1:Column1} |
    |-------------- |
    | ${2:Item1} - |
    ${0}
    -
    3x1tableInsert 3x1 table - Insert table with 3 rows and 1 column. First row is heading. - - | ${1:Column1} |
    |-------------- |
    | ${2:Item1} - |
    | ${3:Item2} |
    ${0}
    -
    4x1tableInsert 4x1 table - Insert table with 4 rows and 1 column. First row is heading. - - | ${1:Column1} |
    |-------------- |
    | ${2:Item1} - |
    | ${3:Item2} |
    | ${4:Item3} |
    ${0}
    -
    5x1tableInsert 5x1 table - Insert table with 5 rows and 1 column. First row is heading. - - | ${1:Column1} |
    |-------------- |
    | ${2:Item1} - |
    | ${3:Item2} |
    | ${4:Item3} |
    | ${5:Item4} - |
    ${0}
    -
    2x2tableInsert 2x2 table - Insert table with 2 rows and 2 columns. First row is heading. - - | ${1:Column1} | ${2:Column2} |
    |--------------- | - --------------- |
    | ${3:Item1.1} | ${4:Item2.1} |
    ${0}
    -
    3x2tableInsert 3x2 table - Insert table with 3 rows and 2 columns. First row is heading. - - | ${1:Column1} | ${2:Column2} |
    |--------------- | - --------------- |
    | ${3:Item1.1} | ${4:Item2.1} |
    | - ${5:Item1.2} | ${6:Item2.2} |
    ${0}
    -
    4x2tableInsert 4x2 table - Insert table with 4 rows and 2 columns. First row is heading. - - | ${1:Column1} | ${2:Column2} |
    |--------------- | - --------------- |
    | ${3:Item1.1} | ${4:Item2.1} |
    | - ${5:Item1.2} | ${6:Item2.2} |
    | ${7:Item1.3} | - ${8:Item2.3} |
    ${0}
    -
    5x2tableInsert 5x2 table - Insert table with 5 rows and 2 columns. First row is heading. - - | ${1:Column1} | ${2:Column2} |
    |--------------- | - --------------- |
    | ${3:Item1.1} | ${4:Item2.1} |
    | - ${4:Item1.2} | ${5:Item2.2} |
    | ${6:Item1.3} | - ${7:Item2.3} |
    | ${8:Item1.4} | ${9:Item2.4} |
    ${0}
    -
    2x3tableInsert 2x3 table - Insert table with 2 rows and 3 columns. First row is heading. - - | ${1:Column1} | ${2:Column2} | ${3:Column3} |
    |---------------- - | --------------- | --------------- |
    | ${4:Item1.1} | - ${5:Item2.1} | ${6:Item3.1} |
    ${0}
    -
    3x3tableInsert 3x3 table - Insert table with 3 rows and 3 columns. First row is heading. - - | ${1:Column1} | ${2:Column2} | ${3:Column3} |
    |---------------- - | --------------- | --------------- |
    | ${4:Item1.1} | - ${5:Item2.1} | ${6:Item3.1} |
    | ${7:Item1.2} | - ${8:Item2.2} | ${9:Item3.2} |
    ${0}
    -
    4x3tableInsert 4x3 table - Insert table with 4 rows and 3 columns. First row is heading. - - | ${1:Column1} | ${2:Column2} | ${3:Column3} |
    |---------------- - | --------------- | --------------- |
    | ${4:Item1.1} | - ${5:Item2.1} | ${6:Item3.1} |
    | ${7:Item1.2} | - ${8:Item2.2} | ${9:Item3.2} |
    | ${10:Item1.3} | - ${11:Item2.3} | ${12:Item3.3} |
    ${0}
    -
    5x3tableInsert 5x3 table - Insert table with 5 rows and 3 columns. First row is heading. - - | ${1:Column1} | ${2:Column2} | ${3:Column3} |
    |---------------- - | --------------- | --------------- |
    | ${4:Item1.1} | - ${5:Item2.1} | ${6:Item3.1} |
    | ${7:Item1.2} | - ${8:Item2.2} | ${9:Item3.2} |
    | ${10:Item1.3} | - ${11:Item2.3} | ${12:Item3.3} |
    | ${13:Item1.4} | - ${14:Item2.4} | ${15:Item3.4} |
    ${0}
    -
    -
    -

    Vue VSCode Snippets

    -
    -

    vue.json

    -

    Available in the following languages:

    -
      -
    • vue
    • -
    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    vbaseVue Single File ComponentBase for Vue File with SCSS - <template>
    - <div>

    - </div>
    </template>

    <script>
    - export default {
    - ${0}
    - }
    </script>

    <style lang="scss" - scoped>

    </style>
    -
    vbase-sassVue Single File Component with SASSBase for Vue File with PostCSS - <template>
    - <div>

    - </div>
    </template>

    <script>
    - export default {
    - ${0}
    - }
    </script>

    <style lang="sass" - scoped>

    </style>
    -
    vbase-lessVue Single File Component with LESSBase for Vue File with PostCSS - <template>
    - <div>

    - </div>
    </template>

    <script>
    - export default {
    - ${0}
    - }
    </script>

    <style lang="less" - scoped>

    </style>
    -
    vbase-pcssVue Single File Component with postcssBase for Vue File with PostCSS - <template>
    - <div>

    - </div>
    </template>

    <script>
    - export default {
    - ${0}
    - }
    </script>

    <style lang="postcss" - scoped>

    </style>
    -
    vbase-cssVue Single File Component with CssBase for Vue File with CSS - <template>
    - <div>

    - </div>
    </template>

    <script>
    - export default {
    - ${0}
    - }
    </script>

    <style scoped>

    </style>
    -
    vbase-stylVue Single File Component with StylusBase for Vue File with Stylus - <template>
    - <div>

    - </div>
    </template>

    <script>
    - export default {
    - ${0}
    - }
    </script>

    <style lang="stylus" - scoped>

    </style>
    -
    vbase-tsVue Single File Component with TypescriptBase for Vue File with Typescript - <template>
    - <div>

    - </div>
    </template>

    <script - lang="ts">
    - import Vue from 'vue'

    - export default Vue.extend({
    - ${0}
    - })
    </script>

    <style scoped>

    </style>
    -
    vbase-nsVue Single File Component with No StyleBase for Vue File with no styles - <template>
    - <div>

    - </div>
    </template>

    <script>
    - export default {
    - ${0}
    - }
    </script>
    -
    vbase-3Vue Single File Component Composition APIBase for Vue File Composition API with SCSS - <template>
    - <div>

    - </div>
    </template>

    <script>
    export - default {
    - setup () {
    - ${0}

    - return {}
    - }
    }
    </script>

    <style lang="scss" - scoped>

    </style>
    -
    vbase-3-reactiveVue Single File Component Composition API ReactiveBase for Vue File Composition API with SCSS - <template>
    - <div>

    - </div>
    </template>

    <script>
    import - { reactive, toRefs } from '@vue/composition-api'

    export - default {
    - setup () {
    - const state = reactive({
    - ${0:count}: ${1:0},
    - })
    -
    - return {
    - ...toRefs(state),
    - }
    - }
    }
    </script>

    <style lang="scss" - scoped>

    </style>
    -
    vbase-3-tsVue Single File Component Composition API with TypescriptBase for Vue File Composition API - Typescript - <template>
    - <div>

    - </div>
    </template>

    <script - lang="ts">
    import { defineComponent } from 'vue'

    export - default defineComponent({
    - setup () {
    - ${0}
    - return {}
    - }
    })
    </script>

    <style - scoped>

    </style>
    -
    vbase-ts-class - Vue Single File Component with Class based Typescript format - Base for Vue File with Class based Typescript format - <template>
    - <div>

    - </div>
    </template>

    <script - lang="ts">
    - import { Component, Vue } from 'vue-property-decorator';

    - @Component
    - export default class ${0} extends Vue {
    -
    - }
    </script>

    <style scoped>

    </style>
    -
    -
    -
    -

    vue-pug.json

    -

    Available in the following languages:

    -
      -
    • jade
    • -
    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    vforVue v-forvfor statement - ${1:div}(v-for="${2:item} in ${2:item}s" - :key="${2:item}.id")
    - | {{ ${2:item} }}
    -
    vmodelVue v-model Directivev-model directive - input(v-model="${1:data}" type="text")
    -
    vmodel-numVue v-model Number Directivev-model directive number input - input(v-model.number="${1:numData}" type="number" - step="1")
    -
    vonVue v-on Shortcut Directivev-on click handler with arguments - @click="${1:handler}(${2:arg}, $event)"
    -
    vel-propsVue Component with Props Bindingcomponent element with props - ${1:component}(:${1:propName}="${0}")
    -
    vsrcVue Image Source Bindingimage source binding - img(:src="'/path/to/images/' + ${1:fileName}" - alt="${2:altText}")
    -
    vstyleVue Style Bindingvue inline style binding - ${1:div}(:style="{ fontSize: ${2:data} + 'px' }")
    -
    vstyle-objVue Style Binding Objectvue inline style binding, objects - ${1:div}(:style="[${2:styleObjectA}, ${3:styleObjectB]}")
    -
    vclassVue Class Bindingvue class binding - ${1:div}(:class="{ ${2:className}: ${3:data} }")
    -
    vclass-objVue Class Binding Objectvue class binding - ${1:div}(:class="[${2:classNameA}, ${3:classNameB}]")
    -
    vclass-obj-multVue Multiple Conditional Class Bindingsvue multiple conditional class bindings - ${1:div}(:class="[${2:classNameA}, {${3:classNameB} : - ${4:condition}}]")
    -
    vanimVue Transition Component with JavaScript Hookstransition component js hooks - transition(
    - mode="out-in"
    - @before-enter="beforeEnter"
    - @enter="enter"

    - @before-leave="beforeLeave"
    - @leave="leave"
    - :css="false"
    )
    -
    vnuxtlVue Nuxt Routing Linknuxt routing link - nuxt-link(to="/${1:page}") ${1:page}
    -
    -
    -
    -

    vue-template.json

    -

    Available in the following languages:

    -
      -
    • html
    • -
    • vue-html
    • -
    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    vforVue v-forvfor statement - <${1:div} v-for="${2:item} in ${2:item}s" - :key="${2:item}.id">
    - {{ ${2:item} }}
    </${1:div}>
    -
    vmodelVue v-model Directivev-model directive - <input v-model="${1:data}" type="text" />
    -
    vmodel-numVue v-model Number Directivev-model directive number input - <input v-model.number="${1:numData}" type="number" - step="1" />
    -
    vonVue v-on Shortcut Directivev-on click handler with arguments - @click="${1:handler}(${2:arg}, $event)"
    -
    vel-propsVue Component with Props Bindingcomponent element with props - <${1:component} - :${1:propName}="${0}"></${1:component}>
    -
    vslot-namedVue Named Slotnamed slot - <template - v-slot:${0:name}>${1:defaultcontent}</template>
    -
    vsrcVue Image Source Bindingimage source binding - <img :src="'/path/to/images/' + ${1:fileName}" - alt="${2:altText}"/>
    -
    vstyleVue Style Bindingvue inline style binding - <${1:div} :style="{ fontSize: ${2:data} + 'px' - }"></${1:div}>
    -
    vstyle-objVue Style Binding Objectvue inline style binding, objects - <${1:div} :style="[${2:styleObjectA}, - ${3:styleObjectB]}"></${1:div}>
    -
    vclassVue Class Bindingvue class binding - <${1:div} :class="{ ${2:className}: ${3:data} - }"></${1:div}>
    -
    vclass-objVue Class Binding Objectvue class binding - <${1:div} :class="[${2:classNameA}, - ${3:classNameB}]"></${1:div}>
    -
    vclass-obj-multVue Multiple Conditional Class Bindingsvue multiple conditional class bindings - <${1:div} :class="[${2:classNameA}, {${3:classNameB} : - ${4:condition}}]"></${1:div}>
    -
    vemit-childVue Emit from ChildVue Emit from Child Component - @change="$$emit('change', $$event.target.value)"
    -
    vemit-parentVue Emit to ParentVue Emit to Parent Component - @change="${1:foo} = $$event"
    -
    vanimVue Transition Component with JavaScript Hookstransition component js hooks - <transition
    - mode="out-in"
    - @before-enter="beforeEnter"
    - @enter="enter"

    - @before-leave="beforeLeave"
    - @leave="leave"
    - :css="false">

    </transition>
    -
    vnuxtlVue Nuxt Routing Linknuxt routing link - <nuxt-link - to="/${1:page}">${1:page}</nuxt-link>
    -
    vroutenameVue Named Routing LinkNamed routing link - <router-link :to="{name: - '${1:name}'}">${2:LinkTitle}</router-link>
    -
    vroutenameparamVue Named Routing Link with ParamsNamed routing link w/ params - <router-link :to="{name: '${1:name}', params:{${2:id}: - '${3:value}'} }">${4:LinkTitle}</router-link>
    -
    vroutepathVue Path Routing LinkPath routing link - <router-link - to="${1:path}">${2:LinkTitle}</router-link>
    -
    -
    -
    -

    vue-script.json

    -

    Available in the following languages:

    -
      -
    • javascript
    • -
    • typescript
    • -
    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    vdataVue DataVue Component Data - data() {
    - return {
    - ${1:key}: ${2:value}
    - }
    },
    -
    vmethodVue Methodsvue method - methods: {
    - ${1:name}() {
    - ${0}
    - }
    },
    -
    vcomputedVue Computedcomputed value - computed: {
    - ${1:name}() {
    - return this.${2:data} ${0}
    - }
    },
    -
    vbeforecreateVue Lifecycle beforeCreatebeforeCreate lifecycle method - beforeCreate () {
    - ${0};
    },
    -
    vcreatedVue Lifecycle createdcreated lifecycle method - created () {
    - ${0};
    },
    -
    vbeforemountVue Lifecycle beforeMountbeforeMount lifecycle method - beforeMount () {
    - ${0};
    },
    -
    vmountedVue Lifecycle mountedmounted lifecycle method - mounted () {
    - ${0};
    },
    -
    vbeforeupdateVue Lifecycle beforeUpdatebeforeUpdate lifecycle method - beforeUpdate () {
    - ${0};
    },
    -
    vupdatedVue Lifecycle updatedupdated lifecycle method - updated () {
    - ${0};
    },
    -
    vbeforedestroyVue Lifecycle beforeDestroybeforeDestroy lifecycle method - beforeDestroy () {
    - ${0};
    },
    -
    vdestroyedVue Lifecycle destroyeddestroyed lifecycle method - destroyed () {
    - ${0};
    },
    -
    vwatcherVue Watchersvue watcher - watch: {
    - ${1:data}(${2:newValue}, ${3:oldValue}) {
    - ${0}
    - }
    },
    -
    vwatcher-optionsVue Watchers with Optionsvue watcher with options - watch: {
    - ${1:data}: {
    - immediate: ${2:true},
    - deep: ${3:true},
    - handler(${4:newValue}, ${5:oldValue}) {
    - ${0}
    - }
    - }
    },
    -
    vpropsVue Props with DefaultVue Props with Default - props: {
    - ${1:propName}: {
    - type: ${2:Number},
    - default: ${0}
    - },
    },
    -
    vimportVue Import FileImport one component into another - import ${1:New} from '@/components/${1:New}.vue';
    -
    vcomponentsVue Import into the Component - Import one component into another, within export statement - - components: {
    - ${1:New},
    },
    -
    vimport-exportVue Import Exportimport a component and include it in export default - import ${1:Name} from '@/components/${1:Name}.vue';

    export - default {
    - components: {
    - ${1:Name}
    - },
    };
    -
    vimport-dynamicVue Import Component DynamicallyImport component that should be lazy loaded - ${1:New} = () => import('@/components/${1:New}.vue')
    -
    vmapstateVue MapStatemap getters inside a vue component - import { mapState } from 'vuex';

    export default - {
    - computed: {
    - ...mapState([
    - ${1:'nameOfState'},
    - ])
    - },
    };
    -
    vmapgettersVue MapGettersmapgetters inside a vue component - import { mapGetters } from 'vuex';

    export default - {
    - computed: {
    - ...mapGetters([
    - ${1:'nameOfGetter'},
    - ])
    - },
    };
    -
    vmapmutationsVue MapMutationsmapmutations inside a vue component - import { mapMutations } from 'vuex';

    export - default {
    - methods: {
    - ...mapMutations([
    - ${1:'nameOfMutation'}, //also supports payload - `this.nameOfMutation(amount)`
    - ])
    - },
    };
    -
    vmapactionsVue MapActionsmapactions inside a vue component - import { mapActions } from 'vuex';

    export default - {
    - methods: {
    - ...mapActions([
    - ${1:'nameOfAction'}, //also supports payload - `this.nameOfAction(amount)`
    - ])
    - },
    };
    -
    vfilterVue Filtervue filter - filters: {
    - ${1:fnName}: function(${2:value}) {
    - return ${2:value}${0};
    - }
    }
    -
    vmixinVue Mixinvue mixin - const ${1:mixinName} = {
    - mounted() {
    - console.log('hello from mixin!');
    - },
    };
    -
    vmixin-useVue Use Mixinvue use mixin - mixins: [${1:mixinName}],
    -
    vc-directVue Custom Directivevue custom directive - Vue.directive('${1:directiveName}', {
    - bind(el, binding, vnode) {
    - el.style.${2:arg} = binding.value.${2:arg};
    - }
    });
    -
    vimport-libVue Import Libraryimport a library - import { ${1:libName} } from '${1:libName}';
    -
    vimport-gsapVue Import GSAPimport gsap library - import gsap from 'gsap';
    -
    vanimhook-jsVue Transition Methods with JavaScript Hookstransition component js hooks - beforeEnter(el) {
    - console.log('beforeEnter');
    },
    enter(el, done) {
    - console.log('enter');
    - done();
    },
    beforeLeave(el) {
    - console.log('beforeLeave');
    },
    leave(el, done) {
    - console.log('leave');
    - done();
    },
    -
    vcommitVue Commit Vuex Store in Methodscommit to vuex store in methods for mutation - ${1:mutationName}() {
    - this.\$store.commit('${1:mutationName}', ${2:payload});
    }
    -
    vdispatchVue Dispatch Vuex Store in Methodsdispatch to vuex store in methods for action - ${1:actionName}() {
    - this.\$store.dispatch('${1:actionName}', ${2:payload});
    }
    -
    vtestUnit Testunit test component - import Vue from 'vue';
    import ${1:HelloWorld} from - './components/${1:HelloWorld}';

    describe('${1:HelloWorld}.vue', - () => {
    - it('${2:should render correct contents}', () => {
    - const Constructor = Vue.extend(${1:HelloWorld});
    - const vm = new Constructor().$mount();
    - expect(vm.$el.querySelector('.hello h1').textContent)
    - .to.equal(${3:'Welcome to Your Vue.js App'});
    - });
    });
    -
    vconfigVue.config.js Importvue.config.js - module.exports = {
    - css: {
    - loaderOptions: {
    - ${1:sass}: {
    - data: `${2:@import '@/styles/_variables.scss';}`
    - }
    - }
    - }
    }
    -
    v3reactiveVue Composition API - ReactiveVue Composition api - reactive - const ${1:name} = reactive({
    - ${2:count}: ${3:0}
    })
    -
    v3computedVue Composition API - ComputedVue Composition api - computed - const ${1:name} = computed(() => {
    - return ${2}
    })
    -
    v3watchVue Composition API - watch - single sourceVue Composition api - watcher single source - watch(() => ${1:foo}, (newValue, oldValue) => {
    - ${2}
    })
    -
    v3watch-arrayVue Composition API - watch - arrayVue Composition api - watch as array - watch([${1:foo}, ${2:bar}], ([new${1}, new${2}], [prev${1}, - prev${2}]) => {
    - ${3}
    })
    -
    v3watcheffectVue Composition API - watchEffectVue Composition api - watchEffect - watchEffect(() => {
    - ${1}
    })
    -
    v3refVue Composition API - Vue refVue Ref - const ${1:name} = ref(${2:initialValue})
    -
    v3onmountedVue Lifecycle Hooks - onMountedVue Mounted Lifecycle hook - onMounted(() => {${1}})
    -
    v3onbeforemountVue Lifecycle Hooks - onBeforeMountVue onBeforeMount Lifecycle hook - onBeforeMount(() => {${1}})
    -
    v3onbeforeupdateVue Lifecycle Hooks - onBeforeUpdateVue onBeforeUpdate Lifecycle hook - onBeforeUpdate(() => {${1}})
    -
    v3onupdatedVue Lifecycle Hooks - onUpdatedVue onUpdated Lifecycle hook - onUpdated(() => {${1}})
    -
    v3onerrorcapturedVue Lifecycle Hooks - onErrorCapturedVue onErrorCaptured Lifecycle hook - onErrorCaptured(() => {${1}})
    -
    v3onunmountedVue Lifecycle Hooks - onUnmounted(destroyed) Vue onUnmounted Lifecycle hook - onUnmounted(() => {${1}})
    -
    v3onbeforeunmountVue Lifecycle Hooks - onBeforeUnmount(beforeDestroy) Vue onBeforeUnmount Lifecycle hook - onBeforeUnmount(() => {${1}})
    -
    vpluginPlugin importImport a plugin to main.js or plugins file - import Vue from 'vue'
    import ${1:VueCompositionApi} from - '${2:@vue/composition-api}'

    Vue.use(${1:VueCompositionApi})
    -
    v3reactive-setupVue Composition API Reactive ScriptVue Composition API Script with Reactive - import { reactive, toRefs } from '@vue/composition-api'

    export - default {
    - setup () {
    - const state = reactive({
    - ${0:count}: ${1:0},
    - })
    -
    - return {
    - ...toRefs(state),
    - }
    - }
    }
    -
    v3useinoptionsUse Composition API within Options APIUse Composition API within Options API - import { ${0:component} } from - '@/composables/${0:component}.js'

    export default - {
    - setup () {
    - const { ${1:name} } = ${0:component}()
    -
    - return {
    - ${1:name}
    - }
    - }
    }
    -
    -
    -
    -

    vue-script-vuex.json

    -

    Available in the following languages:

    -
      -
    • javascript
    • -
    • typescript
    • -
    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    vstoreVuex StoreBase for Vuex store - import Vue from 'vue';
    import Vuex from 'vuex';

    Vue.use(Vuex);

    export - const store = new Vuex.Store({
    - state: {
    - ${1:key}: ${2:value}
    - }
    });
    -
    vgetterVuex Gettersvuex getter - getters: {
    - ${1:value}: state => {
    - return state.${1:value};
    - }
    }
    -
    vmutationVuex Mutationvuex mutation - mutations: {
    - ${1:updateValue}(state, ${3:payload}) {
    - state.${2:value} = ${3:payload};
    - }
    }
    -
    vactionVuex Actionvuex action - actions: {
    - ${1:updateValue}({commit}, ${2:payload}) {
    - commit('${1:updateValue}', ${2:payload});
    - }
    }
    -
    vstore-importVue Import Vuex Storeimport vuex store into main.js - import { store } from './store/index';
    -
    vmoduleVuex Modulevuex module - export default {
    - state: {
    - value: 'my value'
    - },
    - getters: {
    - value: state => {
    - return state.value;
    - }
    - },
    - mutations: {
    - updateValue(state, payload) {
    - state.value = payload;
    - }
    - },
    - actions: {
    - updateValue({commit}, payload) {
    - commit('updateValue', payload);
    - }
    - }
    };
    -
    vstore2Vuex Store 2vuex store 2 - export const state = () => ({
    - value: 'myvalue'
    })

    export const getters = - {
    - getterValue: state => {
    - return state.value
    - }
    }

    export const mutations = {
    - updateValue: (state, payload) => {
    - state.value = payload
    - }
    }

    export const actions = {
    - updateActionValue({ commit }) {
    - commit('updateValue', payload)
    - }
    }
    -
    -
    -
    -

    vue-script-router.json

    -

    Available in the following languages:

    -
      -
    • javascript
    • -
    • typescript
    • -
    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    vrouterVue RouterBase for Vue Router - import Vue from 'vue';
    import VueRouter from - 'vue-router';

    Vue.use(VueRouter);

    export - const router = new VueRouter({
    - base: '/',
    - mode: 'history',
    - routes: [
    - { path: '/path', component: component }
    - ]
    });
    -
    vscrollbehaviorVue Router scrollBehaviorVue Router scrollBehavior - scrollBehavior(to, from, savedPosition) {
    - if(savedPosition) {
    - return savedPosition;
    - } else {
    - return { x: 0, y: 0 };
    - }
    },
    -
    vbeforeeachVue Router beforeEachVue Router global guards beforeEach - router.beforeEach((to, from, next) => {
    - ${1:next();}
    });
    -
    vbeforeresolveVue Router beforeResolveVue Router global guards beforeResolve - router.beforeResolve((to, from, next) => {
    - ${1:next();}
    });
    -
    vaftereachVue Router afterEachVue Router global guards afterEach - router.afterEach((to, from) => {
    -
    });
    -
    vbeforeenterVue Router beforeEnterVue Router per-route guard beforeEnter - beforeEnter(to, from, next) {
    - ${1:next();}
    },
    -
    vbeforerouteenterVue Router beforeRouteEnterVue Router component guards beforeRouteEnter - beforeRouteEnter(to, from, next) {
    - next(vm => {${1:}});
    },
    -
    vbeforerouteupdateVue Router beforeRouteUpdateVue Router component guards beforeRouteUpdate - beforeRouteUpdate(to, from, next) {
    - ${1:next();}
    },
    -
    vbeforerouteleaveVue Router beforeRouteLeaveVue Router component guards beforeRouteLeave - beforeRouteLeave(to, from, next) {
    - ${1:next();}
    },
    -
    vroute-namedVue Router RouteVue Router route with per route code-splitting - {
    - path: '${1:pathName}',
    - name: '${2:routeName}',
    - component: () => import('./${3:pathToComponent}'),
    },
    -
    -
    -
    -

    nuxt-config.json

    -

    Available in the following languages:

    -
      -
    • javascript
    • -
    • typescript
    • -
    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    nfontNuxt Fontlink to include fonts in a nuxt project, in nuxt-config - { rel: 'stylesheet', href: - '${1:https://fonts.googleapis.com/css?family=Montserrat:600|Rufina:700}' - }
    -
    ncssNuxt Use CSS Filelink to css assets such as normalize - css: ['assets/${1:normalize.css}'],
    -
    -
    -
    -

    nuxt-script.json

    -

    Available in the following languages:

    -
      -
    • javascript
    • -
    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    nasyncdataNuxt AsyncNuxt asyncData - async asyncData ({ ${1:params} }) {
    - const { data } = await fetch(`${2:endpoint}`).then(res => - res.json())
    - return { ${3:key}:${4:value} }
    },
    -
    nfetchNuxt FetchNuxt Fetch - async fetch ({ store, ${1:params} }) {
    - let { data } = await fetch('${2:endpoint}').then(res => - res.json())
    - store.commit('${3:MUTATION_TYPE}', data)
    },
    -
    nparamNuxt Route ParamsNuxt Route Params - this.$route.params.${1:id}
    -
    nheadNuxt HeadNuxt Head - head () {
    - return {
    - title: ${1:'Page Title'},
    - meta: [
    - // hid is used as unique identifier. Do not use `vmid` for it - as it will not work
    - { hid: 'description', name: 'description', content: ${2:'My - custom description'} }
    - ]
    - }
    },
    -
    -
    -

    JavaScript (ES6) code snippets

    -
    -

    snippets.json

    -

    Available in the following languages:

    -
      -
    • javascript
    • -
    • typescript
    • -
    • javascriptreact
    • -
    • typescriptreact
    • -
    • html
    • -
    • vue
    • -
    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    impimportImports entire module statement in ES6 syntax - import ${2:moduleName} from '${1:module}';$0
    -
    imnimportNoModuleNameImports entire module in ES6 syntax without module name - import '${1:module}';$0
    -
    imdimportDestructingImports only a portion of the module in ES6 syntax - import { $2 } from '${1:module}';$0
    -
    imeimportEverythingImports everything as alias from the module in ES6 syntax - import * as ${2:alias} from '${1:module}';$0
    -
    imaimportAs - Imports a specific portion of the module by assigning a local - alias in ES6 syntax - - import { ${2:originalName} as ${3:alias} } from - '${1:module}';$0
    -
    rqrrequireRequire a package - require('${1:package}');
    -
    reqrequireToConstRequire a package to const - const ${1:packageName} = require('${1:package}');$0
    -
    mdemoduleExportsModule exports from Common JS, node syntax at ES6 - module.exports = { $0 };
    -
    envexportNamedVariableExport named variable in ES6 syntax - export const ${1:exportVariable} = ${2:localVariable};
    -
    enfexportNamedFunctionExport named function in ES6 syntax - export const ${1:functionName} = (${2:params}) => { $0 }; -
    -
    edfexportDefaultFunctionExport default function in ES6 syntax - export default function ${1:${TM_FILENAME_BASE}}(${2:params}) - { $0 };
    -
    eclexportClassExport default class in ES6 syntax - export default class ${1:className} { $0 };
    -
    eceexportClassExtends - Export default class which extends a base one in ES6 syntax - - export default class ${1:className} extends - ${2:baseclassName} { $0 };
    -
    conconstructorAdd default constructor in a class in ES6 syntax - constructor(${1:params}) { ${0} }
    -
    metmethodCreates a method inside a class in ES6 syntax - ${1:methodName}(${2:params}) { ${0} }
    -
    pgepropertyGetCreates a getter property inside a class in ES6 syntax - get ${1:propertyName}() { return this.${0}; }
    -
    psepropertysetCreates a setter property inside a class in ES6 syntax - set ${1:propertyName}(${2:value}) { ${0}; }
    -
    freforEachCreates a forEach statement in ES6 syntax - ${1:array}.forEach(${2:currentItem} => { ${0} });
    -
    fofforOfIterating over property names of iterable objects - for (const ${1:item} of ${2:object}) { ${0} }
    -
    finforInIterating over property values of iterable objects - for (const ${1:item} in ${2:object}) { ${0} }
    -
    anfnanonymousFunctionCreates an anonymous function in ES6 syntax - (${1:params}) => { ${2} }
    -
    nfnnamedFunctionCreates a named function in ES6 syntax - const ${1:name} = (${2:params}) => { ${3} }
    -
    dobdestructingObject - Creates and assigns a local variable using object destructing - - const {${2:propertyName}} = ${1:objectToDestruct};
    -
    dardestructingArray - Creates and assigns a local variable using array destructing - - const [${2:propertyName}] = ${1:arrayToDestruct};
    -
    stisetInterval - Executes the given function at specified intervals in ES6 syntax - - setInterval(() => { ${2} }, ${0:intervalInms});
    -
    stosetTimeOut - Executes the given function after the specified delay in ES6 - syntax - - setTimeout(() => { ${2} }, ${1:delayInms});
    -
    prompromise - Creates and returns a new Promise in the standard ES6 syntax - - return new Promise((resolve, reject) => { ${1} });
    -
    thencthenCatchAdd the .then and .catch methods to handle promises - .then((${1:result}) => { ${2} }).catch((${3:err}) => { - ${4} });
    -
    casconsoleAssert - If the specified expression is false, the message is written to - the console along with a stack trace - - console.assert(${1:expression}, ${2:object});
    -
    cclconsoleClearClears the console - console.clear();
    -
    ccoconsoleCount - Writes the the number of times that count() has been invoked at - the same line and with the same label - - console.count(${1:label});
    -
    cdbconsoleDebug - Displays a message in the console. Also display a blue right - arrow icon along with the logged message in Safari - - console.debug(${1:object});
    -
    cdiconsoleDir - Prints a JavaScript representation of the specified object - - console.dir(${1:object});
    -
    cerconsoleError - Displays a message in the console and also includes a stack - trace from where the method was called - - console.error(${1:object});
    -
    cgrconsoleGroup - Groups and indents all following output by an additional level, - until console.groupEnd() is called. - - console.group('${1:label}');
    -
    cgeconsoleGroupEndCloses out the corresponding console.group(). - console.groupEnd();
    -
    clgconsoleLogDisplays a message in the console - console.log(${1:object});
    -
    cloconsoleLogObjectDisplays an object in the console with its name - console.log('${1:object} :>> ', ${1:object});
    -
    ctrconsoleTrace - Prints a stack trace from the point where the method was called - - console.trace(${1:object});
    -
    cwaconsoleWarn - Displays a message in the console but also displays a yellow - warning icon along with the logged message - - console.warn(${1:object});
    -
    cinconsoleInfo - Displays a message in the console but also displays a blue - information icon along with the logged message - - console.info(${1:object});
    -
    cltconsoleTableDisplays tabular data as a table. - console.table(${1:object});
    -
    cticonsoleTimeSets starting point for execution time measurement - console.time(${1:object});
    -
    cteconsoleTimeEndSets end point for execution time measurement - console.timeEnd(${1:object});
    -
    -
    -
    -
    -

    VS Code Snippets

    -
    -

    Batchfile

    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    #regionRegion StartFolding Region Start - ::#region
    -
    #endregionRegion EndFolding Region End - ::#endregion
    -
    -
    -
    -

    Coffeescript

    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    #regionRegion StartFolding Region Start - #region
    -
    #endregionRegion EndFolding Region End - #endregion
    -
    -
    -
    -

    C

    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    #regionRegion StartFolding Region Start - #pragma region $0
    -
    #endregionRegion EndFolding Region End - #pragma endregion
    -
    -
    -
    -

    CPP

    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    #regionRegion StartFolding Region Start - #pragma region $0
    -
    #endregionRegion EndFolding Region End - #pragma endregion
    -
    -
    -
    -

    Csharp

    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    #regionRegion StartFolding Region Start - #region $0
    -
    #endregionRegion EndFolding Region End - #endregion
    -
    -
    -
    -

    Fsharp

    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    #regionRegion StartFolding Region Start - //#region $0
    -
    #endregionRegion EndFolding Region End - //#endregion
    -
    -
    -
    -

    Groovy

    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    replacereplace(dir: …, includes: …, token: …, value: …)Replace(...) - replace(dir:"${1:dirName}", includes:"${2:*.*}", - token:"${3:tokenName}", value:"\${${4:value}}")$0
    -
    docDoc BlockDoc block comment - /**
    - * $0
    - */
    -
    keykey: "value" (Hash Pair) - ${1:key}: ${2:"${3:value}"}
    -
    threadThread.start { … }Thread.start { ... } - Thread.start {
    - $0
    }
    -
    threadThread.startDaemon { … }Thread.startDaemon { ... } - Thread.startDaemon {
    - $0
    }
    -
    casecase … breakcase ... break - case ${1:CASE_NAME}:
    - $2
    break$0
    -
    instanceinstance … (Singleton)Singleton instance + Getter - private static $1 instance

    static $1 - getInstance(${2:args}) {
    - if (!instance) instance = new $1(${2:args})
    - return instance
    }
    -
    tcclass … extends GroovyTestCase { … }GroovyTestCase class - class $1 extends GroovyTestCase {

    - $0
    }
    -
    copycopy(file: …, tofile: …)Copy file - copy(file:"${1:sourceFile}", tofile:"${2:targetFile}")
    -
    copycopy(todir: …) { fileset(dir: …) { include … exclude }Copy fileset todir w/ include/exclude - copy(todir:"${1:targetDir}") {
    - fileset(dir:"${2:sourceDir}") {
    - include(name:"${3:includeName}")
    - exclude(name:"${4:excludeName}")
    - }
    }
    -
    copycopy(todir: …) { fileset:dir …) }Copy fileset todir - copy(todir:"${1:targetDir}") {
    - fileset(dir:"${2:sourceDir}")
    }
    -
    cvclosure = { … }Closure block - def ${1:closureName} = { ${2:args} ->
    - $0
    }
    -
    forinfor(… in …) { … }For-loop - for (${1:element} in ${2:collection}) {
    - $0
    }
    -
    mkdirmkdir(dir: …)mkdir - mkdir(dir:"${1:dirName}")
    -
    pprintprint - print $0
    -
    plprintlnprintln - println $0
    -
    runarunAfter() { … }runAfter() { ... } - runAfter(${1:delay}) {
    - $0
    }
    -
    setupsetUp() { … }setup() { ... } - void setUp() {
    - $0
    }
    -
    sleepsleep(secs) { … // on interrupt do }sleep with interrupt - sleep(${1:secs}) {
    - ${2:// on interrupt do}
    }
    -
    sleepsleep(secs)sleep - sleep(${1:secs})
    -
    sortsort { … }sort - sort {
    - $0
    }
    -
    mainstatic main() { … }main method - static main(args) {
    - $0
    }
    -
    switchswitch … caseSwitch-Case block - switch(${1:value}) {
    - case ${2:CASE}:
    - $3
    - break$0
    }
    -
    switchswitch … case … defaultSwitch-Case-Default block - switch(${1:value}) {
    - case ${3:CASE}:
    - $4
    - break$0
    - default:
    - $2
    - break
    }
    -
    teartearDown() { … }tearDown() { ... } - void tearDown() {
    - $0
    }
    -
    ttest()test method - void test$1() {
    - $0
    }
    -
    vvarvar - ${1:def} ${2:var}${3: = ${0:null}}
    -
    -
    -
    -

    Java

    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    #regionRegion StartFolding Region Start - //#region
    -
    #endregionRegion EndFolding Region End - //#endregion
    -
    -
    -
    -

    Javascript

    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    definedefine moduledefine module - define([
    - 'require',
    - '${1:dependency}'
    ], function(require, ${2:factory}) {
    - 'use strict';
    - $0
    });
    -
    forFor LoopFor Loop - for (let ${1:index} = 0; ${1:index} < ${2:array}.length; - ${1:index}++) {
    - const ${3:element} = ${2:array}[${1:index}];
    - $0
    }
    -
    foreachFor-Each LoopFor-Each Loop - ${1:array}.forEach(${2:element} => {
    - $0
    });
    -
    forinFor-In LoopFor-In Loop - for (const ${1:key} in ${2:object}) {
    - if (${2:object}.hasOwnProperty(${1:key})) {
    - const ${3:element} = ${2:object}[${1:key}];
    - $0
    - }
    }
    -
    forofFor-Of LoopFor-Of Loop - for (const ${1:iterator} of ${2:object}) {
    - $0
    }
    -
    functionFunction StatementFunction Statement - function ${1:name}(${2:params}) {
    - $0
    }
    -
    ifIf StatementIf Statement - if (${1:condition}) {
    - $0
    }
    -
    ifelseIf-Else StatementIf-Else Statement - if (${1:condition}) {
    - $0
    } else {
    -
    }
    -
    newNew StatementNew Statement - const ${1:name} = new ${2:type}(${3:arguments});$0
    -
    switchSwitch StatementSwitch Statement - switch (${1:key}) {
    - case ${2:value}:
    - $0
    - break;

    - default:
    - break;
    }
    -
    whileWhile StatementWhile Statement - while (${1:condition}) {
    - $0
    }
    -
    dowhileDo-While StatementDo-While Statement - do {
    - $0
    } while (${1:condition});
    -
    trycatchTry-Catch StatementTry-Catch Statement - try {
    - $0
    } catch (${1:error}) {
    -
    }
    -
    settimeoutSet Timeout FunctionSet Timeout Function - setTimeout(() => {
    - $0
    }, ${1:timeout});
    -
    setintervalSet Interval FunctionSet Interval Function - setInterval(() => {
    - $0
    }, ${1:interval});
    -
    import statementImport external module.Import external module. - import { $0 } from "${1:module}";
    -
    #regionRegion StartFolding Region Start - //#region $0
    -
    #endregionRegion EndFolding Region End - //#endregion
    -
    logLog to the consoleLog to the console - console.log($1);
    -
    warnLog warning to consoleLog warning to the console - console.warn($1);
    -
    errorLog error to consoleLog error to the console - console.error($1);
    -
    -
    -
    -

    Markdown

    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    boldInsert bold textInsert bold text - **${1:${TM_SELECTED_TEXT}}**$0
    -
    italicInsert italic textInsert italic text - *${1:${TM_SELECTED_TEXT}}*$0
    -
    quoteInsert quoted textInsert quoted text - > ${1:${TM_SELECTED_TEXT}}
    -
    codeInsert inline codeInsert inline code - `${1:${TM_SELECTED_TEXT}}`$0
    -
    fenced codeblockInsert fenced code blockInsert fenced code block - ```${1:language}
    ${TM_SELECTED_TEXT}$0
    ```
    -
    heading1Insert heading level 1Insert heading level 1 - # ${1:${TM_SELECTED_TEXT}}
    -
    heading2Insert heading level 2Insert heading level 2 - ## ${1:${TM_SELECTED_TEXT}}
    -
    heading3Insert heading level 3Insert heading level 3 - ### ${1:${TM_SELECTED_TEXT}}
    -
    heading4Insert heading level 4Insert heading level 4 - #### ${1:${TM_SELECTED_TEXT}}
    -
    heading5Insert heading level 5Insert heading level 5 - ##### ${1:${TM_SELECTED_TEXT}}
    -
    heading6Insert heading level 6Insert heading level 6 - ###### ${1:${TM_SELECTED_TEXT}}
    -
    unordered listInsert unordered listInsert unordered list - - ${1:first}
    - ${2:second}
    - ${3:third}
    $0
    -
    ordered listInsert ordered listInsert ordered list - 1. ${1:first}
    2. ${2:second}
    3. ${3:third}
    $0
    -
    horizontal ruleInsert horizontal ruleInsert horizontal rule - ----------
    -
    linkInsert linkInsert link - [${TM_SELECTED_TEXT:${1:text}}](https://${2:link})$0
    -
    imageInsert imageInsert image - ![${TM_SELECTED_TEXT:${1:alt}}](https://${2:link})$0
    -
    strikethroughInsert strikethroughInsert strikethrough - ~~${1:${TM_SELECTED_TEXT}}~~
    -
    -
    -
    -

    PHP

    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    classclass …Class definition - class ${1:ClassName} ${2:extends ${3:AnotherClass}} - ${4:implements ${5:Interface}}
    {
    - $0
    }

    -
    doc_classPHPDoc class …Documented Class Declaration - /**
    - * ${6:undocumented class}
    - */
    class ${1:ClassName} ${2:extends ${3:AnotherClass}} - ${4:implements ${5:Interface}}
    {
    - $0
    }

    -
    confunction __construct - ${1:public} function __construct(${2:${3:Type} $${4:var}${5: - = ${6:null}}}) {
    - \$this->${4:var} = $${4:var};$0
    }
    -
    doc_vPHPDoc propertyDocumented Class Variable - /** @var ${1:Type} $${2:var} ${3:description} */
    ${4:protected} - $${2:var}${5: = ${6:null}};$0
    -
    doc_fPHPDoc function …Documented function - /**
    - * ${1:undocumented function summary}
    - *
    - * ${2:Undocumented function long description}
    - *
    ${3: * @param ${4:Type} $${5:var} ${6:Description}}
    ${7: - * @return ${8:type}}
    ${9: * @throws ${10:conditon}}
    - **/
    ${11:public }function - ${12:FunctionName}(${13:${14:${4:Type} }$${5:var}${15: = - ${16:null}}})
    {
    - ${0:# code...}
    }
    -
    paramPHPDoc param …Paramater documentation - * @param ${1:Type} ${2:var} ${3:Description}$0
    -
    funfunction …Function - ${1:public }function ${2:FunctionName}(${3:${4:${5:Type} - }$${6:var}${7: = ${8:null}}})
    {
    - ${0:# code...}
    }
    -
    traittrait …Trait - /**
    - * $1
    - */
    trait ${2:TraitName}
    {
    - $0
    }

    -
    defdefine(…, …)Definition - define('$1', ${2:'$3'});
    $0
    -
    dodo … while …Do-While loop - do {
    - ${0:# code...}
    } while (${1:$${2:a} <= ${3:10}});
    -
    whilewhile …While-loop - while (${1:$${2:a} <= ${3:10}}) {
    - ${0:# code...}
    }
    -
    ifif …If block - if (${1:condition}) {
    - ${0:# code...}
    }
    -
    ifelseif … else …If Else block - if (${1:condition}) {
    - ${2:# code...}
    } else {
    - ${3:# code...}
    }
    $0
    -
    if?$… = ( … ) ? … : …Ternary conditional assignment - $${1:retVal} = (${2:condition}) ? ${3:a} : ${4:b} ;
    -
    elseelse …Else block - else {
    - ${0:# code...}
    }
    -
    elseifelseif …Elseif block - elseif (${1:condition}) {
    - ${0:# code...}
    }
    -
    forfor …For-loop - for ($${1:i}=${2:0}; $${1:i} < $3; $${1:i}++) {
    - ${0:# code...}
    }
    -
    foreachforeach …Foreach loop - foreach ($${1:variable} as $${2:key} ${3:=> $${4:value}}) - {
    - ${0:# code...}
    }
    -
    array$… = array (…)Array initializer - $${1:arrayName} = array('$2' => $3${4:,} $0);
    -
    shorray$… = […]Array initializer - $${1:arrayName} = ['$2' => $3${4:,} $0];
    -
    keyval… => …Key-Value initializer - '$1' => $2${3:,} $0
    -
    switchswitch …Switch block - switch (\$${1:variable}) {
    - case '${2:value}':
    - ${3:# code...}
    - break;
    - $0
    - default:
    - ${4:# code...}
    - break;
    }
    -
    casecase …Case Block - case '${1:value}':
    - ${0:# code...}
    - break;
    -
    this$this->…$this->... - \$this->$0;
    -
    ethisecho $this->…Echo this - echo \$this->$0;
    -
    throwThrow ExceptionThrow exception - throw new $1Exception(${2:"${3:Error Processing - Request}"}${4:, ${5:1}});
    $0
    -
    #regionRegion StartFolding Region Start - #region
    -
    #endregionRegion EndFolding Region End - #endregion
    -
    tryTry Catch BlockTry catch block - try {
    - ${1://code...}
    } catch (${2:\Throwable} ${3:\$th}) {
    - ${4://throw \$th;}
    }
    -
    -
    -
    -

    Powershell

    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    #regionRegion StartFolding Region Start - #region $0
    -
    #endregionRegion EndFolding Region End - #endregion
    -
    -
    -
    -

    Swift

    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    printprintprint("...") - print("$1") $0
    -
    printvprint valueprint("\(...)") - print("\($1)") $0
    -
    whilewhilewhile statement - while ${1:condition} {
    - $0
    }
    -
    repeatrepeat-whilerepeat-while statement - repeat {
    - $0
    } while ${1:condition}
    -
    forforfor-in statement - for ${1:item} in ${2:collection} {
    - $0
    }
    -
    ififif statement - if ${1:condition} {
    - $0
    }
    -
    elifelse ifelse clause with a nested if statement - else if ${1:condition} {
    - $0
    }
    -
    elseelseelse clause - else {
    - $0
    }
    -
    ifletif letif statement with optional binding - if let ${1:value} = ${2:optional} {
    - $0
    }
    -
    guardguardguard statement - guard ${1:condition} else {
    - $0
    }
    -
    guardletguard letguard statement with optional binding - guard let ${1:value} = ${2:optional} else {
    - $0
    }
    -
    switchswitchswitch statement - switch ${1:value} {
    case ${2:pattern}:
    - $0
    default:
    -
    }
    -
    dododo statement - do {
    - $0
    } catch ${1:error} {
    - $2
    }
    -
    funcfuncfunction declaration - func ${1:name}(${2:parameters}) -> ${3:Type} {
    - $0
    }
    -
    structstructstruct declaration - struct ${1:Name} {

    - $0
    }
    -
    enumenumenum declaration - enum ${1:Name} {

    - case $0
    }
    -
    classclassclass declaration - class ${1:Name} {

    - $0
    }
    -
    protocolprotocolprotocol declaration - protocol ${1:Name} {

    - $0
    }
    -
    extensionextensionextension declaration - extension ${1:Type} {

    - $0
    }
    -
    -
    -
    -

    Typescript

    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    ctorConstructorConstructor - /**
    - *
    - */
    constructor() {
    - super();
    - $0
    }
    -
    classClass DefinitionClass Definition - class ${1:name} {
    - constructor(${2:parameters}) {
    - $0
    - }
    }
    -
    public methodPublic Method DefinitionPublic Method Definition - /**
    - * ${1:name}
    - */
    public ${1:name}() {
    - $0
    }
    -
    private methodPrivate Method DefinitionPrivate Method Definition - private ${1:name}() {
    - $0
    }
    -
    import statementImport external module.Import external module. - import { $0 } from "${1:module}";
    -
    getProperty getterProperty getter -
    public get ${1:value}() : ${2:string} {
    - ${3:return $0}
    }

    -
    logLog to the consoleLog to the console - console.log($1);
    $0
    -
    warnLog warning to consoleLog warning to the console - console.warn($1);
    $0
    -
    errorLog error to consoleLog error to the console - console.error($1);
    $0
    -
    propDefine a full propertyDefine a full property -
    private _${1:value} : ${2:string};
    public get - ${1:value}() : ${2:string} {
    - return this._${1:value};
    }
    public set ${1:value}(v : - ${2:string}) {
    - this._${1:value} = v;
    }

    -
    refTriple-slash referenceTriple-slash reference - /// <reference path="$1" />
    $0
    -
    setProperty setterProperty setter -
    public set ${1:value}(v : ${2:string}) {
    - this.$3 = v;
    }

    -
    throwThrow ExceptionThrow Exception - throw new Error("$1");
    $0
    -
    forFor LoopFor Loop - for (let ${1:index} = 0; ${1:index} < ${2:array}.length; - ${1:index}++) {
    - const ${3:element} = ${2:array}[${1:index}];
    - $0
    }
    -
    foreach =>For-Each Loop using =>For-Each Loop using => - ${1:array}.forEach(${2:element} => {
    - $0
    });
    -
    forinFor-In LoopFor-In Loop - for (const ${1:key} in ${2:object}) {
    - if (Object.prototype.hasOwnProperty.call(${2:object}, - ${1:key})) {
    - const ${3:element} = ${2:object}[${1:key}];
    - $0
    - }
    }
    -
    forofFor-Of LoopFor-Of Loop - for (const ${1:iterator} of ${2:object}) {
    - $0
    }
    -
    forawaitofFor-Await-Of LoopFor-Await-Of Loop - for await (const ${1:iterator} of ${2:object}) {
    - $0
    }
    -
    functionFunction StatementFunction Statement - function ${1:name}(${2:params}:${3:type}) {
    - $0
    }
    -
    ifIf StatementIf Statement - if (${1:condition}) {
    - $0
    }
    -
    ifelseIf-Else StatementIf-Else Statement - if (${1:condition}) {
    - $0
    } else {
    -
    }
    -
    newNew StatementNew Statement - const ${1:name} = new ${2:type}(${3:arguments});$0
    -
    switchSwitch StatementSwitch Statement - switch (${1:key}) {
    - case ${2:value}:
    - $0
    - break;

    - default:
    - break;
    }
    -
    whileWhile StatementWhile Statement - while (${1:condition}) {
    - $0
    }
    -
    dowhileDo-While StatementDo-While Statement - do {
    - $0
    } while (${1:condition});
    -
    trycatchTry-Catch StatementTry-Catch Statement - try {
    - $0
    } catch (${1:error}) {
    -
    }
    -
    settimeoutSet Timeout FunctionSet Timeout Function - setTimeout(() => {
    - $0
    }, ${1:timeout});
    -
    #regionRegion StartFolding Region Start - //#region $0
    -
    #endregionRegion EndFolding Region End - //#endregion
    -
    newpromisenew PromiseCreate a new Promise - new Promise<$1:type>((resolve, reject) => {
    - $1
    })
    -
    async functionAsync Function StatementAsync Function Statement - async function ${1:name}(${2:params}:${3:type}) {
    - $0
    }
    -
    async arrow functionAsync Function ExpressionAsync Function Expression - async (${1:params}:${2:type}) => {
    - $0
    }
    -
    -
    -
    -

    VB

    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    forFor Next LoopFor Next Loop - For ${1:index} As ${2:ObjectType} = ${3:lower} To - ${4:Upper}
    - $0
    Next ${1:index}
    -
    foreFor Each...NextFor Each...Next - For Each ${1:Variable} As ${2:ObjectType} In - ${3:Collection}
    - $0
    Next
    -
    foriFor i...Next iFor i...Next i - For i As ${1:Integer} = ${2:Lower} To ${3:Upper}
    - $0
    Next i
    -
    forjFor j...Next jFor j...Next j - For j As ${1:Integer} = ${2:Lower} To ${3:Upper}
    - $0
    Next j
    -
    pfPublic Function...Public Function... - Public Function ${1:FunctionName}(${2:ParameterList}) As - ${3:ReturnType}
    - Try
    - $0
    - Catch ex As Exception
    - End Try
    - Return ${3:ReturnValue}
    End Function
    -
    psPublic Sub ...Public Sub ... - Public Sub ${1:ProcedureName}(${2:ParameterList})
    - Try
    - $0
    - Catch ex As Exception
    - End Try
    End Sub
    -
    whileWhile ... End WhileWhile ... End While - While ${1:Boolean}
    - $0
    End While
    -
    #RegionRegion StartFolding Region Start - #Region $0
    -
    #End RegionRegion EndFolding Region End - #End Region
    -
    -
    -
    - - Go to top - - - - - - - diff --git a/test/view-light.html b/test/view-light.html deleted file mode 100644 index f3b2e5d..0000000 --- a/test/view-light.html +++ /dev/null @@ -1,5220 +0,0 @@ - - - - - -

    Snippets Ranger

    -
    -

    Table of Contents

    - -
    -
    -

    User Snippets

    -
    -

    Markdown

    - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    testtest - [
    ${CLIPBOARD/^(.+)$/'$1',/gm}
    ]
    -
    upUpper the second mirrored tab stop - ${1:title}
    ${1/(.*)/${1:/upcase}/}
    ${1/(.*)/${1:/upcase}/}
    $0
    -
    -
    -
    -
    -

    Extension Snippets

    -

    markdownlint

    -
    -

    snippets.json

    -

    Available in the following languages:

    -
      -
    • markdown
    • -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    markdownlint-disableinsertMarkdownLintDisableComment - Disables one or more rules by name (MD013), alias (line-length), - or tag (whitespace). Multiple rules are space-delimited (MD018 - MD019). If no rules are specified, all rules are disabled. Takes - effect starting with the line the comment is on. - - <!-- markdownlint-disable ${1:MD000 }-->
    -
    markdownlint-enableinsertMarkdownLintEnableComment - Enables one or more rules by name (MD013), alias (line-length), - or tag (whitespace). Multiple rules are space-delimited (MD018 - MD019). If no rules are specified, all rules are enabled. Takes - effect starting with the line the comment is on. - - <!-- markdownlint-enable ${1:MD000 }-->
    -
    markdownlint-disable-fileinsertMarkdownLintDisableFileComment - Disables one or more rules by name (MD013), alias (line-length), - or tag (whitespace). Multiple rules are space-delimited (MD018 - MD019). If no rules are specified, all rules are disabled. - Applies to the entire file. - - <!-- markdownlint-disable-file ${1:MD000 }-->
    -
    markdownlint-enable-fileinsertMarkdownLintEnableFileComment - Enables one or more rules by name (MD013), alias (line-length), - or tag (whitespace). Multiple rules are space-delimited (MD018 - MD019). If no rules are specified, all rules are enabled. - Applies to the entire file. - - <!-- markdownlint-enable-file ${1:MD000 }-->
    -
    markdownlint-captureinsertMarkdownLintCaptureComment - Captures the current rule configuration. Takes effect starting - with the line the comment is on. - - <!-- markdownlint-capture -->
    -
    markdownlint-restoreinsertMarkdownLintRestoreComment - Restores the most recently captured rule configuration. Defaults - to the document's initial configuration. Takes effect starting - with the line the comment is on. - - <!-- markdownlint-restore -->
    -
    markdownlint-configure-fileinsertMarkdownLintConfigureFileComment - Configures one or more rules by name (MD013), alias - (line-length), or tag (whitespace) using the same JSON format as - the "markdownlint.config" object. Applies to the entire file. - - <!-- markdownlint-configure-file { ${1:"MD013": { - "line_length": 100 \}} } -->
    -
    -
    -

    Markdown Snippets

    -
    -

    snippets.code-snippets

    -

    Available in the following languages:

    -
      -
    • markdown
    • -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    taskInsert task listInsert task list - - [${1| ,x|}] ${2:text}
    ${0}
    -
    task2Insert task list 2Insert task list with 2 tasks - - [${1| ,x|}] ${2:text}
    - [${3| ,x|}] ${4:text}
    ${0}
    -
    task3Insert task list 3Insert task list with 3 tasks - - [${1| ,x|}] ${2:text}
    - [${3| ,x|}] ${4:text}
    - - [${5| ,x|}] ${6:text}
    ${0}
    -
    task4Insert task list 4Insert task list with 4 tasks - - [${1| ,x|}] ${2:text}
    - [${3| ,x|}] ${4:text}
    - - [${5| ,x|}] ${6:text}
    - [${7| ,x|}] ${8:text}
    ${0}
    -
    task5Insert task list 5Insert task list with 5 tasks - - [${1| ,x|}] ${2:text}
    - [${3| ,x|}] ${4:text}
    - - [${5| ,x|}] ${6:text}
    - [${7| ,x|}] ${8:text}
    - - [${9| ,x|}] ${10:text}
    ${0}
    -
    tableInsert table - Insert table with 2 rows and 3 columns. First row is heading. - - | ${1:Column1} | ${2:Column2} | ${3:Column3} |
    |-------------- - | -------------- | -------------- |
    | ${4:Item1} | - ${5:Item1} | ${6:Item1} |
    ${0}
    -
    2x1tableInsert 2x1 table - Insert table with 2 rows and 1 column. First row is heading. - - | ${1:Column1} |
    |-------------- |
    | ${2:Item1} - |
    ${0}
    -
    3x1tableInsert 3x1 table - Insert table with 3 rows and 1 column. First row is heading. - - | ${1:Column1} |
    |-------------- |
    | ${2:Item1} - |
    | ${3:Item2} |
    ${0}
    -
    4x1tableInsert 4x1 table - Insert table with 4 rows and 1 column. First row is heading. - - | ${1:Column1} |
    |-------------- |
    | ${2:Item1} - |
    | ${3:Item2} |
    | ${4:Item3} |
    ${0}
    -
    5x1tableInsert 5x1 table - Insert table with 5 rows and 1 column. First row is heading. - - | ${1:Column1} |
    |-------------- |
    | ${2:Item1} - |
    | ${3:Item2} |
    | ${4:Item3} |
    | ${5:Item4} - |
    ${0}
    -
    2x2tableInsert 2x2 table - Insert table with 2 rows and 2 columns. First row is heading. - - | ${1:Column1} | ${2:Column2} |
    |--------------- | - --------------- |
    | ${3:Item1.1} | ${4:Item2.1} |
    ${0}
    -
    3x2tableInsert 3x2 table - Insert table with 3 rows and 2 columns. First row is heading. - - | ${1:Column1} | ${2:Column2} |
    |--------------- | - --------------- |
    | ${3:Item1.1} | ${4:Item2.1} |
    | - ${5:Item1.2} | ${6:Item2.2} |
    ${0}
    -
    4x2tableInsert 4x2 table - Insert table with 4 rows and 2 columns. First row is heading. - - | ${1:Column1} | ${2:Column2} |
    |--------------- | - --------------- |
    | ${3:Item1.1} | ${4:Item2.1} |
    | - ${5:Item1.2} | ${6:Item2.2} |
    | ${7:Item1.3} | - ${8:Item2.3} |
    ${0}
    -
    5x2tableInsert 5x2 table - Insert table with 5 rows and 2 columns. First row is heading. - - | ${1:Column1} | ${2:Column2} |
    |--------------- | - --------------- |
    | ${3:Item1.1} | ${4:Item2.1} |
    | - ${4:Item1.2} | ${5:Item2.2} |
    | ${6:Item1.3} | - ${7:Item2.3} |
    | ${8:Item1.4} | ${9:Item2.4} |
    ${0}
    -
    2x3tableInsert 2x3 table - Insert table with 2 rows and 3 columns. First row is heading. - - | ${1:Column1} | ${2:Column2} | ${3:Column3} |
    |---------------- - | --------------- | --------------- |
    | ${4:Item1.1} | - ${5:Item2.1} | ${6:Item3.1} |
    ${0}
    -
    3x3tableInsert 3x3 table - Insert table with 3 rows and 3 columns. First row is heading. - - | ${1:Column1} | ${2:Column2} | ${3:Column3} |
    |---------------- - | --------------- | --------------- |
    | ${4:Item1.1} | - ${5:Item2.1} | ${6:Item3.1} |
    | ${7:Item1.2} | - ${8:Item2.2} | ${9:Item3.2} |
    ${0}
    -
    4x3tableInsert 4x3 table - Insert table with 4 rows and 3 columns. First row is heading. - - | ${1:Column1} | ${2:Column2} | ${3:Column3} |
    |---------------- - | --------------- | --------------- |
    | ${4:Item1.1} | - ${5:Item2.1} | ${6:Item3.1} |
    | ${7:Item1.2} | - ${8:Item2.2} | ${9:Item3.2} |
    | ${10:Item1.3} | - ${11:Item2.3} | ${12:Item3.3} |
    ${0}
    -
    5x3tableInsert 5x3 table - Insert table with 5 rows and 3 columns. First row is heading. - - | ${1:Column1} | ${2:Column2} | ${3:Column3} |
    |---------------- - | --------------- | --------------- |
    | ${4:Item1.1} | - ${5:Item2.1} | ${6:Item3.1} |
    | ${7:Item1.2} | - ${8:Item2.2} | ${9:Item3.2} |
    | ${10:Item1.3} | - ${11:Item2.3} | ${12:Item3.3} |
    | ${13:Item1.4} | - ${14:Item2.4} | ${15:Item3.4} |
    ${0}
    -
    -
    -

    Vue VSCode Snippets

    -
    -

    vue.json

    -

    Available in the following languages:

    -
      -
    • vue
    • -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    vbaseVue Single File ComponentBase for Vue File with SCSS - <template>
    - <div>

    - </div>
    </template>

    <script>
    - export default {
    - ${0}
    - }
    </script>

    <style lang="scss" - scoped>

    </style>
    -
    vbase-sassVue Single File Component with SASSBase for Vue File with PostCSS - <template>
    - <div>

    - </div>
    </template>

    <script>
    - export default {
    - ${0}
    - }
    </script>

    <style lang="sass" - scoped>

    </style>
    -
    vbase-lessVue Single File Component with LESSBase for Vue File with PostCSS - <template>
    - <div>

    - </div>
    </template>

    <script>
    - export default {
    - ${0}
    - }
    </script>

    <style lang="less" - scoped>

    </style>
    -
    vbase-pcssVue Single File Component with postcssBase for Vue File with PostCSS - <template>
    - <div>

    - </div>
    </template>

    <script>
    - export default {
    - ${0}
    - }
    </script>

    <style lang="postcss" - scoped>

    </style>
    -
    vbase-cssVue Single File Component with CssBase for Vue File with CSS - <template>
    - <div>

    - </div>
    </template>

    <script>
    - export default {
    - ${0}
    - }
    </script>

    <style scoped>

    </style>
    -
    vbase-stylVue Single File Component with StylusBase for Vue File with Stylus - <template>
    - <div>

    - </div>
    </template>

    <script>
    - export default {
    - ${0}
    - }
    </script>

    <style lang="stylus" - scoped>

    </style>
    -
    vbase-tsVue Single File Component with TypescriptBase for Vue File with Typescript - <template>
    - <div>

    - </div>
    </template>

    <script - lang="ts">
    - import Vue from 'vue'

    - export default Vue.extend({
    - ${0}
    - })
    </script>

    <style scoped>

    </style>
    -
    vbase-nsVue Single File Component with No StyleBase for Vue File with no styles - <template>
    - <div>

    - </div>
    </template>

    <script>
    - export default {
    - ${0}
    - }
    </script>
    -
    vbase-3Vue Single File Component Composition APIBase for Vue File Composition API with SCSS - <template>
    - <div>

    - </div>
    </template>

    <script>
    export - default {
    - setup () {
    - ${0}

    - return {}
    - }
    }
    </script>

    <style lang="scss" - scoped>

    </style>
    -
    vbase-3-reactiveVue Single File Component Composition API ReactiveBase for Vue File Composition API with SCSS - <template>
    - <div>

    - </div>
    </template>

    <script>
    import - { reactive, toRefs } from '@vue/composition-api'

    export - default {
    - setup () {
    - const state = reactive({
    - ${0:count}: ${1:0},
    - })
    -
    - return {
    - ...toRefs(state),
    - }
    - }
    }
    </script>

    <style lang="scss" - scoped>

    </style>
    -
    vbase-3-tsVue Single File Component Composition API with TypescriptBase for Vue File Composition API - Typescript - <template>
    - <div>

    - </div>
    </template>

    <script - lang="ts">
    import { defineComponent } from 'vue'

    export - default defineComponent({
    - setup () {
    - ${0}
    - return {}
    - }
    })
    </script>

    <style - scoped>

    </style>
    -
    vbase-ts-class - Vue Single File Component with Class based Typescript format - Base for Vue File with Class based Typescript format - <template>
    - <div>

    - </div>
    </template>

    <script - lang="ts">
    - import { Component, Vue } from 'vue-property-decorator';

    - @Component
    - export default class ${0} extends Vue {
    -
    - }
    </script>

    <style scoped>

    </style>
    -
    -
    -
    -

    vue-pug.json

    -

    Available in the following languages:

    -
      -
    • jade
    • -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    vforVue v-forvfor statement - ${1:div}(v-for="${2:item} in ${2:item}s" - :key="${2:item}.id")
    - | {{ ${2:item} }}
    -
    vmodelVue v-model Directivev-model directive - input(v-model="${1:data}" type="text")
    -
    vmodel-numVue v-model Number Directivev-model directive number input - input(v-model.number="${1:numData}" type="number" - step="1")
    -
    vonVue v-on Shortcut Directivev-on click handler with arguments - @click="${1:handler}(${2:arg}, $event)"
    -
    vel-propsVue Component with Props Bindingcomponent element with props - ${1:component}(:${1:propName}="${0}")
    -
    vsrcVue Image Source Bindingimage source binding - img(:src="'/path/to/images/' + ${1:fileName}" - alt="${2:altText}")
    -
    vstyleVue Style Bindingvue inline style binding - ${1:div}(:style="{ fontSize: ${2:data} + 'px' }")
    -
    vstyle-objVue Style Binding Objectvue inline style binding, objects - ${1:div}(:style="[${2:styleObjectA}, ${3:styleObjectB]}")
    -
    vclassVue Class Bindingvue class binding - ${1:div}(:class="{ ${2:className}: ${3:data} }")
    -
    vclass-objVue Class Binding Objectvue class binding - ${1:div}(:class="[${2:classNameA}, ${3:classNameB}]")
    -
    vclass-obj-multVue Multiple Conditional Class Bindingsvue multiple conditional class bindings - ${1:div}(:class="[${2:classNameA}, {${3:classNameB} : - ${4:condition}}]")
    -
    vanimVue Transition Component with JavaScript Hookstransition component js hooks - transition(
    - mode="out-in"
    - @before-enter="beforeEnter"
    - @enter="enter"

    - @before-leave="beforeLeave"
    - @leave="leave"
    - :css="false"
    )
    -
    vnuxtlVue Nuxt Routing Linknuxt routing link - nuxt-link(to="/${1:page}") ${1:page}
    -
    -
    -
    -

    vue-template.json

    -

    Available in the following languages:

    -
      -
    • html
    • -
    • vue-html
    • -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    vforVue v-forvfor statement - <${1:div} v-for="${2:item} in ${2:item}s" - :key="${2:item}.id">
    - {{ ${2:item} }}
    </${1:div}>
    -
    vmodelVue v-model Directivev-model directive - <input v-model="${1:data}" type="text" />
    -
    vmodel-numVue v-model Number Directivev-model directive number input - <input v-model.number="${1:numData}" type="number" - step="1" />
    -
    vonVue v-on Shortcut Directivev-on click handler with arguments - @click="${1:handler}(${2:arg}, $event)"
    -
    vel-propsVue Component with Props Bindingcomponent element with props - <${1:component} - :${1:propName}="${0}"></${1:component}>
    -
    vslot-namedVue Named Slotnamed slot - <template - v-slot:${0:name}>${1:defaultcontent}</template>
    -
    vsrcVue Image Source Bindingimage source binding - <img :src="'/path/to/images/' + ${1:fileName}" - alt="${2:altText}"/>
    -
    vstyleVue Style Bindingvue inline style binding - <${1:div} :style="{ fontSize: ${2:data} + 'px' - }"></${1:div}>
    -
    vstyle-objVue Style Binding Objectvue inline style binding, objects - <${1:div} :style="[${2:styleObjectA}, - ${3:styleObjectB]}"></${1:div}>
    -
    vclassVue Class Bindingvue class binding - <${1:div} :class="{ ${2:className}: ${3:data} - }"></${1:div}>
    -
    vclass-objVue Class Binding Objectvue class binding - <${1:div} :class="[${2:classNameA}, - ${3:classNameB}]"></${1:div}>
    -
    vclass-obj-multVue Multiple Conditional Class Bindingsvue multiple conditional class bindings - <${1:div} :class="[${2:classNameA}, {${3:classNameB} : - ${4:condition}}]"></${1:div}>
    -
    vemit-childVue Emit from ChildVue Emit from Child Component - @change="$$emit('change', $$event.target.value)"
    -
    vemit-parentVue Emit to ParentVue Emit to Parent Component - @change="${1:foo} = $$event"
    -
    vanimVue Transition Component with JavaScript Hookstransition component js hooks - <transition
    - mode="out-in"
    - @before-enter="beforeEnter"
    - @enter="enter"

    - @before-leave="beforeLeave"
    - @leave="leave"
    - :css="false">

    </transition>
    -
    vnuxtlVue Nuxt Routing Linknuxt routing link - <nuxt-link - to="/${1:page}">${1:page}</nuxt-link>
    -
    vroutenameVue Named Routing LinkNamed routing link - <router-link :to="{name: - '${1:name}'}">${2:LinkTitle}</router-link>
    -
    vroutenameparamVue Named Routing Link with ParamsNamed routing link w/ params - <router-link :to="{name: '${1:name}', params:{${2:id}: - '${3:value}'} }">${4:LinkTitle}</router-link>
    -
    vroutepathVue Path Routing LinkPath routing link - <router-link - to="${1:path}">${2:LinkTitle}</router-link>
    -
    -
    -
    -

    vue-script.json

    -

    Available in the following languages:

    -
      -
    • javascript
    • -
    • typescript
    • -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    vdataVue DataVue Component Data - data() {
    - return {
    - ${1:key}: ${2:value}
    - }
    },
    -
    vmethodVue Methodsvue method - methods: {
    - ${1:name}() {
    - ${0}
    - }
    },
    -
    vcomputedVue Computedcomputed value - computed: {
    - ${1:name}() {
    - return this.${2:data} ${0}
    - }
    },
    -
    vbeforecreateVue Lifecycle beforeCreatebeforeCreate lifecycle method - beforeCreate () {
    - ${0};
    },
    -
    vcreatedVue Lifecycle createdcreated lifecycle method - created () {
    - ${0};
    },
    -
    vbeforemountVue Lifecycle beforeMountbeforeMount lifecycle method - beforeMount () {
    - ${0};
    },
    -
    vmountedVue Lifecycle mountedmounted lifecycle method - mounted () {
    - ${0};
    },
    -
    vbeforeupdateVue Lifecycle beforeUpdatebeforeUpdate lifecycle method - beforeUpdate () {
    - ${0};
    },
    -
    vupdatedVue Lifecycle updatedupdated lifecycle method - updated () {
    - ${0};
    },
    -
    vbeforedestroyVue Lifecycle beforeDestroybeforeDestroy lifecycle method - beforeDestroy () {
    - ${0};
    },
    -
    vdestroyedVue Lifecycle destroyeddestroyed lifecycle method - destroyed () {
    - ${0};
    },
    -
    vwatcherVue Watchersvue watcher - watch: {
    - ${1:data}(${2:newValue}, ${3:oldValue}) {
    - ${0}
    - }
    },
    -
    vwatcher-optionsVue Watchers with Optionsvue watcher with options - watch: {
    - ${1:data}: {
    - immediate: ${2:true},
    - deep: ${3:true},
    - handler(${4:newValue}, ${5:oldValue}) {
    - ${0}
    - }
    - }
    },
    -
    vpropsVue Props with DefaultVue Props with Default - props: {
    - ${1:propName}: {
    - type: ${2:Number},
    - default: ${0}
    - },
    },
    -
    vimportVue Import FileImport one component into another - import ${1:New} from '@/components/${1:New}.vue';
    -
    vcomponentsVue Import into the Component - Import one component into another, within export statement - - components: {
    - ${1:New},
    },
    -
    vimport-exportVue Import Exportimport a component and include it in export default - import ${1:Name} from '@/components/${1:Name}.vue';

    export - default {
    - components: {
    - ${1:Name}
    - },
    };
    -
    vimport-dynamicVue Import Component DynamicallyImport component that should be lazy loaded - ${1:New} = () => import('@/components/${1:New}.vue')
    -
    vmapstateVue MapStatemap getters inside a vue component - import { mapState } from 'vuex';

    export default - {
    - computed: {
    - ...mapState([
    - ${1:'nameOfState'},
    - ])
    - },
    };
    -
    vmapgettersVue MapGettersmapgetters inside a vue component - import { mapGetters } from 'vuex';

    export default - {
    - computed: {
    - ...mapGetters([
    - ${1:'nameOfGetter'},
    - ])
    - },
    };
    -
    vmapmutationsVue MapMutationsmapmutations inside a vue component - import { mapMutations } from 'vuex';

    export - default {
    - methods: {
    - ...mapMutations([
    - ${1:'nameOfMutation'}, //also supports payload - `this.nameOfMutation(amount)`
    - ])
    - },
    };
    -
    vmapactionsVue MapActionsmapactions inside a vue component - import { mapActions } from 'vuex';

    export default - {
    - methods: {
    - ...mapActions([
    - ${1:'nameOfAction'}, //also supports payload - `this.nameOfAction(amount)`
    - ])
    - },
    };
    -
    vfilterVue Filtervue filter - filters: {
    - ${1:fnName}: function(${2:value}) {
    - return ${2:value}${0};
    - }
    }
    -
    vmixinVue Mixinvue mixin - const ${1:mixinName} = {
    - mounted() {
    - console.log('hello from mixin!');
    - },
    };
    -
    vmixin-useVue Use Mixinvue use mixin - mixins: [${1:mixinName}],
    -
    vc-directVue Custom Directivevue custom directive - Vue.directive('${1:directiveName}', {
    - bind(el, binding, vnode) {
    - el.style.${2:arg} = binding.value.${2:arg};
    - }
    });
    -
    vimport-libVue Import Libraryimport a library - import { ${1:libName} } from '${1:libName}';
    -
    vimport-gsapVue Import GSAPimport gsap library - import gsap from 'gsap';
    -
    vanimhook-jsVue Transition Methods with JavaScript Hookstransition component js hooks - beforeEnter(el) {
    - console.log('beforeEnter');
    },
    enter(el, done) {
    - console.log('enter');
    - done();
    },
    beforeLeave(el) {
    - console.log('beforeLeave');
    },
    leave(el, done) {
    - console.log('leave');
    - done();
    },
    -
    vcommitVue Commit Vuex Store in Methodscommit to vuex store in methods for mutation - ${1:mutationName}() {
    - this.\$store.commit('${1:mutationName}', ${2:payload});
    }
    -
    vdispatchVue Dispatch Vuex Store in Methodsdispatch to vuex store in methods for action - ${1:actionName}() {
    - this.\$store.dispatch('${1:actionName}', ${2:payload});
    }
    -
    vtestUnit Testunit test component - import Vue from 'vue';
    import ${1:HelloWorld} from - './components/${1:HelloWorld}';

    describe('${1:HelloWorld}.vue', - () => {
    - it('${2:should render correct contents}', () => {
    - const Constructor = Vue.extend(${1:HelloWorld});
    - const vm = new Constructor().$mount();
    - expect(vm.$el.querySelector('.hello h1').textContent)
    - .to.equal(${3:'Welcome to Your Vue.js App'});
    - });
    });
    -
    vconfigVue.config.js Importvue.config.js - module.exports = {
    - css: {
    - loaderOptions: {
    - ${1:sass}: {
    - data: `${2:@import '@/styles/_variables.scss';}`
    - }
    - }
    - }
    }
    -
    v3reactiveVue Composition API - ReactiveVue Composition api - reactive - const ${1:name} = reactive({
    - ${2:count}: ${3:0}
    })
    -
    v3computedVue Composition API - ComputedVue Composition api - computed - const ${1:name} = computed(() => {
    - return ${2}
    })
    -
    v3watchVue Composition API - watch - single sourceVue Composition api - watcher single source - watch(() => ${1:foo}, (newValue, oldValue) => {
    - ${2}
    })
    -
    v3watch-arrayVue Composition API - watch - arrayVue Composition api - watch as array - watch([${1:foo}, ${2:bar}], ([new${1}, new${2}], [prev${1}, - prev${2}]) => {
    - ${3}
    })
    -
    v3watcheffectVue Composition API - watchEffectVue Composition api - watchEffect - watchEffect(() => {
    - ${1}
    })
    -
    v3refVue Composition API - Vue refVue Ref - const ${1:name} = ref(${2:initialValue})
    -
    v3onmountedVue Lifecycle Hooks - onMountedVue Mounted Lifecycle hook - onMounted(() => {${1}})
    -
    v3onbeforemountVue Lifecycle Hooks - onBeforeMountVue onBeforeMount Lifecycle hook - onBeforeMount(() => {${1}})
    -
    v3onbeforeupdateVue Lifecycle Hooks - onBeforeUpdateVue onBeforeUpdate Lifecycle hook - onBeforeUpdate(() => {${1}})
    -
    v3onupdatedVue Lifecycle Hooks - onUpdatedVue onUpdated Lifecycle hook - onUpdated(() => {${1}})
    -
    v3onerrorcapturedVue Lifecycle Hooks - onErrorCapturedVue onErrorCaptured Lifecycle hook - onErrorCaptured(() => {${1}})
    -
    v3onunmountedVue Lifecycle Hooks - onUnmounted(destroyed) Vue onUnmounted Lifecycle hook - onUnmounted(() => {${1}})
    -
    v3onbeforeunmountVue Lifecycle Hooks - onBeforeUnmount(beforeDestroy) Vue onBeforeUnmount Lifecycle hook - onBeforeUnmount(() => {${1}})
    -
    vpluginPlugin importImport a plugin to main.js or plugins file - import Vue from 'vue'
    import ${1:VueCompositionApi} from - '${2:@vue/composition-api}'

    Vue.use(${1:VueCompositionApi})
    -
    v3reactive-setupVue Composition API Reactive ScriptVue Composition API Script with Reactive - import { reactive, toRefs } from '@vue/composition-api'

    export - default {
    - setup () {
    - const state = reactive({
    - ${0:count}: ${1:0},
    - })
    -
    - return {
    - ...toRefs(state),
    - }
    - }
    }
    -
    v3useinoptionsUse Composition API within Options APIUse Composition API within Options API - import { ${0:component} } from - '@/composables/${0:component}.js'

    export default - {
    - setup () {
    - const { ${1:name} } = ${0:component}()
    -
    - return {
    - ${1:name}
    - }
    - }
    }
    -
    -
    -
    -

    vue-script-vuex.json

    -

    Available in the following languages:

    -
      -
    • javascript
    • -
    • typescript
    • -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    vstoreVuex StoreBase for Vuex store - import Vue from 'vue';
    import Vuex from 'vuex';

    Vue.use(Vuex);

    export - const store = new Vuex.Store({
    - state: {
    - ${1:key}: ${2:value}
    - }
    });
    -
    vgetterVuex Gettersvuex getter - getters: {
    - ${1:value}: state => {
    - return state.${1:value};
    - }
    }
    -
    vmutationVuex Mutationvuex mutation - mutations: {
    - ${1:updateValue}(state, ${3:payload}) {
    - state.${2:value} = ${3:payload};
    - }
    }
    -
    vactionVuex Actionvuex action - actions: {
    - ${1:updateValue}({commit}, ${2:payload}) {
    - commit('${1:updateValue}', ${2:payload});
    - }
    }
    -
    vstore-importVue Import Vuex Storeimport vuex store into main.js - import { store } from './store/index';
    -
    vmoduleVuex Modulevuex module - export default {
    - state: {
    - value: 'my value'
    - },
    - getters: {
    - value: state => {
    - return state.value;
    - }
    - },
    - mutations: {
    - updateValue(state, payload) {
    - state.value = payload;
    - }
    - },
    - actions: {
    - updateValue({commit}, payload) {
    - commit('updateValue', payload);
    - }
    - }
    };
    -
    vstore2Vuex Store 2vuex store 2 - export const state = () => ({
    - value: 'myvalue'
    })

    export const getters = - {
    - getterValue: state => {
    - return state.value
    - }
    }

    export const mutations = {
    - updateValue: (state, payload) => {
    - state.value = payload
    - }
    }

    export const actions = {
    - updateActionValue({ commit }) {
    - commit('updateValue', payload)
    - }
    }
    -
    -
    -
    -

    vue-script-router.json

    -

    Available in the following languages:

    -
      -
    • javascript
    • -
    • typescript
    • -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    vrouterVue RouterBase for Vue Router - import Vue from 'vue';
    import VueRouter from - 'vue-router';

    Vue.use(VueRouter);

    export - const router = new VueRouter({
    - base: '/',
    - mode: 'history',
    - routes: [
    - { path: '/path', component: component }
    - ]
    });
    -
    vscrollbehaviorVue Router scrollBehaviorVue Router scrollBehavior - scrollBehavior(to, from, savedPosition) {
    - if(savedPosition) {
    - return savedPosition;
    - } else {
    - return { x: 0, y: 0 };
    - }
    },
    -
    vbeforeeachVue Router beforeEachVue Router global guards beforeEach - router.beforeEach((to, from, next) => {
    - ${1:next();}
    });
    -
    vbeforeresolveVue Router beforeResolveVue Router global guards beforeResolve - router.beforeResolve((to, from, next) => {
    - ${1:next();}
    });
    -
    vaftereachVue Router afterEachVue Router global guards afterEach - router.afterEach((to, from) => {
    -
    });
    -
    vbeforeenterVue Router beforeEnterVue Router per-route guard beforeEnter - beforeEnter(to, from, next) {
    - ${1:next();}
    },
    -
    vbeforerouteenterVue Router beforeRouteEnterVue Router component guards beforeRouteEnter - beforeRouteEnter(to, from, next) {
    - next(vm => {${1:}});
    },
    -
    vbeforerouteupdateVue Router beforeRouteUpdateVue Router component guards beforeRouteUpdate - beforeRouteUpdate(to, from, next) {
    - ${1:next();}
    },
    -
    vbeforerouteleaveVue Router beforeRouteLeaveVue Router component guards beforeRouteLeave - beforeRouteLeave(to, from, next) {
    - ${1:next();}
    },
    -
    vroute-namedVue Router RouteVue Router route with per route code-splitting - {
    - path: '${1:pathName}',
    - name: '${2:routeName}',
    - component: () => import('./${3:pathToComponent}'),
    },
    -
    -
    -
    -

    nuxt-config.json

    -

    Available in the following languages:

    -
      -
    • javascript
    • -
    • typescript
    • -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    nfontNuxt Fontlink to include fonts in a nuxt project, in nuxt-config - { rel: 'stylesheet', href: - '${1:https://fonts.googleapis.com/css?family=Montserrat:600|Rufina:700}' - }
    -
    ncssNuxt Use CSS Filelink to css assets such as normalize - css: ['assets/${1:normalize.css}'],
    -
    -
    -
    -

    nuxt-script.json

    -

    Available in the following languages:

    -
      -
    • javascript
    • -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    nasyncdataNuxt AsyncNuxt asyncData - async asyncData ({ ${1:params} }) {
    - const { data } = await fetch(`${2:endpoint}`).then(res => - res.json())
    - return { ${3:key}:${4:value} }
    },
    -
    nfetchNuxt FetchNuxt Fetch - async fetch ({ store, ${1:params} }) {
    - let { data } = await fetch('${2:endpoint}').then(res => - res.json())
    - store.commit('${3:MUTATION_TYPE}', data)
    },
    -
    nparamNuxt Route ParamsNuxt Route Params - this.$route.params.${1:id}
    -
    nheadNuxt HeadNuxt Head - head () {
    - return {
    - title: ${1:'Page Title'},
    - meta: [
    - // hid is used as unique identifier. Do not use `vmid` for it - as it will not work
    - { hid: 'description', name: 'description', content: ${2:'My - custom description'} }
    - ]
    - }
    },
    -
    -
    -

    JavaScript (ES6) code snippets

    -
    -

    snippets.json

    -

    Available in the following languages:

    -
      -
    • javascript
    • -
    • typescript
    • -
    • javascriptreact
    • -
    • typescriptreact
    • -
    • html
    • -
    • vue
    • -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    impimportImports entire module statement in ES6 syntax - import ${2:moduleName} from '${1:module}';$0
    -
    imnimportNoModuleNameImports entire module in ES6 syntax without module name - import '${1:module}';$0
    -
    imdimportDestructingImports only a portion of the module in ES6 syntax - import { $2 } from '${1:module}';$0
    -
    imeimportEverythingImports everything as alias from the module in ES6 syntax - import * as ${2:alias} from '${1:module}';$0
    -
    imaimportAs - Imports a specific portion of the module by assigning a local - alias in ES6 syntax - - import { ${2:originalName} as ${3:alias} } from - '${1:module}';$0
    -
    rqrrequireRequire a package - require('${1:package}');
    -
    reqrequireToConstRequire a package to const - const ${1:packageName} = require('${1:package}');$0
    -
    mdemoduleExportsModule exports from Common JS, node syntax at ES6 - module.exports = { $0 };
    -
    envexportNamedVariableExport named variable in ES6 syntax - export const ${1:exportVariable} = ${2:localVariable};
    -
    enfexportNamedFunctionExport named function in ES6 syntax - export const ${1:functionName} = (${2:params}) => { $0 }; -
    -
    edfexportDefaultFunctionExport default function in ES6 syntax - export default function ${1:${TM_FILENAME_BASE}}(${2:params}) - { $0 };
    -
    eclexportClassExport default class in ES6 syntax - export default class ${1:className} { $0 };
    -
    eceexportClassExtends - Export default class which extends a base one in ES6 syntax - - export default class ${1:className} extends - ${2:baseclassName} { $0 };
    -
    conconstructorAdd default constructor in a class in ES6 syntax - constructor(${1:params}) { ${0} }
    -
    metmethodCreates a method inside a class in ES6 syntax - ${1:methodName}(${2:params}) { ${0} }
    -
    pgepropertyGetCreates a getter property inside a class in ES6 syntax - get ${1:propertyName}() { return this.${0}; }
    -
    psepropertysetCreates a setter property inside a class in ES6 syntax - set ${1:propertyName}(${2:value}) { ${0}; }
    -
    freforEachCreates a forEach statement in ES6 syntax - ${1:array}.forEach(${2:currentItem} => { ${0} });
    -
    fofforOfIterating over property names of iterable objects - for (const ${1:item} of ${2:object}) { ${0} }
    -
    finforInIterating over property values of iterable objects - for (const ${1:item} in ${2:object}) { ${0} }
    -
    anfnanonymousFunctionCreates an anonymous function in ES6 syntax - (${1:params}) => { ${2} }
    -
    nfnnamedFunctionCreates a named function in ES6 syntax - const ${1:name} = (${2:params}) => { ${3} }
    -
    dobdestructingObject - Creates and assigns a local variable using object destructing - - const {${2:propertyName}} = ${1:objectToDestruct};
    -
    dardestructingArray - Creates and assigns a local variable using array destructing - - const [${2:propertyName}] = ${1:arrayToDestruct};
    -
    stisetInterval - Executes the given function at specified intervals in ES6 syntax - - setInterval(() => { ${2} }, ${0:intervalInms});
    -
    stosetTimeOut - Executes the given function after the specified delay in ES6 - syntax - - setTimeout(() => { ${2} }, ${1:delayInms});
    -
    prompromise - Creates and returns a new Promise in the standard ES6 syntax - - return new Promise((resolve, reject) => { ${1} });
    -
    thencthenCatchAdd the .then and .catch methods to handle promises - .then((${1:result}) => { ${2} }).catch((${3:err}) => { - ${4} });
    -
    casconsoleAssert - If the specified expression is false, the message is written to - the console along with a stack trace - - console.assert(${1:expression}, ${2:object});
    -
    cclconsoleClearClears the console - console.clear();
    -
    ccoconsoleCount - Writes the the number of times that count() has been invoked at - the same line and with the same label - - console.count(${1:label});
    -
    cdbconsoleDebug - Displays a message in the console. Also display a blue right - arrow icon along with the logged message in Safari - - console.debug(${1:object});
    -
    cdiconsoleDir - Prints a JavaScript representation of the specified object - - console.dir(${1:object});
    -
    cerconsoleError - Displays a message in the console and also includes a stack - trace from where the method was called - - console.error(${1:object});
    -
    cgrconsoleGroup - Groups and indents all following output by an additional level, - until console.groupEnd() is called. - - console.group('${1:label}');
    -
    cgeconsoleGroupEndCloses out the corresponding console.group(). - console.groupEnd();
    -
    clgconsoleLogDisplays a message in the console - console.log(${1:object});
    -
    cloconsoleLogObjectDisplays an object in the console with its name - console.log('${1:object} :>> ', ${1:object});
    -
    ctrconsoleTrace - Prints a stack trace from the point where the method was called - - console.trace(${1:object});
    -
    cwaconsoleWarn - Displays a message in the console but also displays a yellow - warning icon along with the logged message - - console.warn(${1:object});
    -
    cinconsoleInfo - Displays a message in the console but also displays a blue - information icon along with the logged message - - console.info(${1:object});
    -
    cltconsoleTableDisplays tabular data as a table. - console.table(${1:object});
    -
    cticonsoleTimeSets starting point for execution time measurement - console.time(${1:object});
    -
    cteconsoleTimeEndSets end point for execution time measurement - console.timeEnd(${1:object});
    -
    -
    -
    -
    -

    VS Code Snippets

    -
    -

    Batchfile

    - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    #regionRegion StartFolding Region Start - ::#region
    -
    #endregionRegion EndFolding Region End - ::#endregion
    -
    -
    -
    -

    Coffeescript

    - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    #regionRegion StartFolding Region Start - #region
    -
    #endregionRegion EndFolding Region End - #endregion
    -
    -
    -
    -

    C

    - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    #regionRegion StartFolding Region Start - #pragma region $0
    -
    #endregionRegion EndFolding Region End - #pragma endregion
    -
    -
    -
    -

    CPP

    - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    #regionRegion StartFolding Region Start - #pragma region $0
    -
    #endregionRegion EndFolding Region End - #pragma endregion
    -
    -
    -
    -

    Csharp

    - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    #regionRegion StartFolding Region Start - #region $0
    -
    #endregionRegion EndFolding Region End - #endregion
    -
    -
    -
    -

    Fsharp

    - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    #regionRegion StartFolding Region Start - //#region $0
    -
    #endregionRegion EndFolding Region End - //#endregion
    -
    -
    -
    -

    Groovy

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    replacereplace(dir: …, includes: …, token: …, value: …)Replace(...) - replace(dir:"${1:dirName}", includes:"${2:*.*}", - token:"${3:tokenName}", value:"\${${4:value}}")$0
    -
    docDoc BlockDoc block comment - /**
    - * $0
    - */
    -
    keykey: "value" (Hash Pair) - ${1:key}: ${2:"${3:value}"}
    -
    threadThread.start { … }Thread.start { ... } - Thread.start {
    - $0
    }
    -
    threadThread.startDaemon { … }Thread.startDaemon { ... } - Thread.startDaemon {
    - $0
    }
    -
    casecase … breakcase ... break - case ${1:CASE_NAME}:
    - $2
    break$0
    -
    instanceinstance … (Singleton)Singleton instance + Getter - private static $1 instance

    static $1 - getInstance(${2:args}) {
    - if (!instance) instance = new $1(${2:args})
    - return instance
    }
    -
    tcclass … extends GroovyTestCase { … }GroovyTestCase class - class $1 extends GroovyTestCase {

    - $0
    }
    -
    copycopy(file: …, tofile: …)Copy file - copy(file:"${1:sourceFile}", tofile:"${2:targetFile}")
    -
    copycopy(todir: …) { fileset(dir: …) { include … exclude }Copy fileset todir w/ include/exclude - copy(todir:"${1:targetDir}") {
    - fileset(dir:"${2:sourceDir}") {
    - include(name:"${3:includeName}")
    - exclude(name:"${4:excludeName}")
    - }
    }
    -
    copycopy(todir: …) { fileset:dir …) }Copy fileset todir - copy(todir:"${1:targetDir}") {
    - fileset(dir:"${2:sourceDir}")
    }
    -
    cvclosure = { … }Closure block - def ${1:closureName} = { ${2:args} ->
    - $0
    }
    -
    forinfor(… in …) { … }For-loop - for (${1:element} in ${2:collection}) {
    - $0
    }
    -
    mkdirmkdir(dir: …)mkdir - mkdir(dir:"${1:dirName}")
    -
    pprintprint - print $0
    -
    plprintlnprintln - println $0
    -
    runarunAfter() { … }runAfter() { ... } - runAfter(${1:delay}) {
    - $0
    }
    -
    setupsetUp() { … }setup() { ... } - void setUp() {
    - $0
    }
    -
    sleepsleep(secs) { … // on interrupt do }sleep with interrupt - sleep(${1:secs}) {
    - ${2:// on interrupt do}
    }
    -
    sleepsleep(secs)sleep - sleep(${1:secs})
    -
    sortsort { … }sort - sort {
    - $0
    }
    -
    mainstatic main() { … }main method - static main(args) {
    - $0
    }
    -
    switchswitch … caseSwitch-Case block - switch(${1:value}) {
    - case ${2:CASE}:
    - $3
    - break$0
    }
    -
    switchswitch … case … defaultSwitch-Case-Default block - switch(${1:value}) {
    - case ${3:CASE}:
    - $4
    - break$0
    - default:
    - $2
    - break
    }
    -
    teartearDown() { … }tearDown() { ... } - void tearDown() {
    - $0
    }
    -
    ttest()test method - void test$1() {
    - $0
    }
    -
    vvarvar - ${1:def} ${2:var}${3: = ${0:null}}
    -
    -
    -
    -

    Java

    - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    #regionRegion StartFolding Region Start - //#region
    -
    #endregionRegion EndFolding Region End - //#endregion
    -
    -
    -
    -

    Javascript

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    definedefine moduledefine module - define([
    - 'require',
    - '${1:dependency}'
    ], function(require, ${2:factory}) {
    - 'use strict';
    - $0
    });
    -
    forFor LoopFor Loop - for (let ${1:index} = 0; ${1:index} < ${2:array}.length; - ${1:index}++) {
    - const ${3:element} = ${2:array}[${1:index}];
    - $0
    }
    -
    foreachFor-Each LoopFor-Each Loop - ${1:array}.forEach(${2:element} => {
    - $0
    });
    -
    forinFor-In LoopFor-In Loop - for (const ${1:key} in ${2:object}) {
    - if (${2:object}.hasOwnProperty(${1:key})) {
    - const ${3:element} = ${2:object}[${1:key}];
    - $0
    - }
    }
    -
    forofFor-Of LoopFor-Of Loop - for (const ${1:iterator} of ${2:object}) {
    - $0
    }
    -
    functionFunction StatementFunction Statement - function ${1:name}(${2:params}) {
    - $0
    }
    -
    ifIf StatementIf Statement - if (${1:condition}) {
    - $0
    }
    -
    ifelseIf-Else StatementIf-Else Statement - if (${1:condition}) {
    - $0
    } else {
    -
    }
    -
    newNew StatementNew Statement - const ${1:name} = new ${2:type}(${3:arguments});$0
    -
    switchSwitch StatementSwitch Statement - switch (${1:key}) {
    - case ${2:value}:
    - $0
    - break;

    - default:
    - break;
    }
    -
    whileWhile StatementWhile Statement - while (${1:condition}) {
    - $0
    }
    -
    dowhileDo-While StatementDo-While Statement - do {
    - $0
    } while (${1:condition});
    -
    trycatchTry-Catch StatementTry-Catch Statement - try {
    - $0
    } catch (${1:error}) {
    -
    }
    -
    settimeoutSet Timeout FunctionSet Timeout Function - setTimeout(() => {
    - $0
    }, ${1:timeout});
    -
    setintervalSet Interval FunctionSet Interval Function - setInterval(() => {
    - $0
    }, ${1:interval});
    -
    import statementImport external module.Import external module. - import { $0 } from "${1:module}";
    -
    #regionRegion StartFolding Region Start - //#region $0
    -
    #endregionRegion EndFolding Region End - //#endregion
    -
    logLog to the consoleLog to the console - console.log($1);
    -
    warnLog warning to consoleLog warning to the console - console.warn($1);
    -
    errorLog error to consoleLog error to the console - console.error($1);
    -
    -
    -
    -

    Markdown

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    boldInsert bold textInsert bold text - **${1:${TM_SELECTED_TEXT}}**$0
    -
    italicInsert italic textInsert italic text - *${1:${TM_SELECTED_TEXT}}*$0
    -
    quoteInsert quoted textInsert quoted text - > ${1:${TM_SELECTED_TEXT}}
    -
    codeInsert inline codeInsert inline code - `${1:${TM_SELECTED_TEXT}}`$0
    -
    fenced codeblockInsert fenced code blockInsert fenced code block - ```${1:language}
    ${TM_SELECTED_TEXT}$0
    ```
    -
    heading1Insert heading level 1Insert heading level 1 - # ${1:${TM_SELECTED_TEXT}}
    -
    heading2Insert heading level 2Insert heading level 2 - ## ${1:${TM_SELECTED_TEXT}}
    -
    heading3Insert heading level 3Insert heading level 3 - ### ${1:${TM_SELECTED_TEXT}}
    -
    heading4Insert heading level 4Insert heading level 4 - #### ${1:${TM_SELECTED_TEXT}}
    -
    heading5Insert heading level 5Insert heading level 5 - ##### ${1:${TM_SELECTED_TEXT}}
    -
    heading6Insert heading level 6Insert heading level 6 - ###### ${1:${TM_SELECTED_TEXT}}
    -
    unordered listInsert unordered listInsert unordered list - - ${1:first}
    - ${2:second}
    - ${3:third}
    $0
    -
    ordered listInsert ordered listInsert ordered list - 1. ${1:first}
    2. ${2:second}
    3. ${3:third}
    $0
    -
    horizontal ruleInsert horizontal ruleInsert horizontal rule - ----------
    -
    linkInsert linkInsert link - [${TM_SELECTED_TEXT:${1:text}}](https://${2:link})$0
    -
    imageInsert imageInsert image - ![${TM_SELECTED_TEXT:${1:alt}}](https://${2:link})$0
    -
    strikethroughInsert strikethroughInsert strikethrough - ~~${1:${TM_SELECTED_TEXT}}~~
    -
    -
    -
    -

    PHP

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    classclass …Class definition - class ${1:ClassName} ${2:extends ${3:AnotherClass}} - ${4:implements ${5:Interface}}
    {
    - $0
    }

    -
    doc_classPHPDoc class …Documented Class Declaration - /**
    - * ${6:undocumented class}
    - */
    class ${1:ClassName} ${2:extends ${3:AnotherClass}} - ${4:implements ${5:Interface}}
    {
    - $0
    }

    -
    confunction __construct - ${1:public} function __construct(${2:${3:Type} $${4:var}${5: - = ${6:null}}}) {
    - \$this->${4:var} = $${4:var};$0
    }
    -
    doc_vPHPDoc propertyDocumented Class Variable - /** @var ${1:Type} $${2:var} ${3:description} */
    ${4:protected} - $${2:var}${5: = ${6:null}};$0
    -
    doc_fPHPDoc function …Documented function - /**
    - * ${1:undocumented function summary}
    - *
    - * ${2:Undocumented function long description}
    - *
    ${3: * @param ${4:Type} $${5:var} ${6:Description}}
    ${7: - * @return ${8:type}}
    ${9: * @throws ${10:conditon}}
    - **/
    ${11:public }function - ${12:FunctionName}(${13:${14:${4:Type} }$${5:var}${15: = - ${16:null}}})
    {
    - ${0:# code...}
    }
    -
    paramPHPDoc param …Paramater documentation - * @param ${1:Type} ${2:var} ${3:Description}$0
    -
    funfunction …Function - ${1:public }function ${2:FunctionName}(${3:${4:${5:Type} - }$${6:var}${7: = ${8:null}}})
    {
    - ${0:# code...}
    }
    -
    traittrait …Trait - /**
    - * $1
    - */
    trait ${2:TraitName}
    {
    - $0
    }

    -
    defdefine(…, …)Definition - define('$1', ${2:'$3'});
    $0
    -
    dodo … while …Do-While loop - do {
    - ${0:# code...}
    } while (${1:$${2:a} <= ${3:10}});
    -
    whilewhile …While-loop - while (${1:$${2:a} <= ${3:10}}) {
    - ${0:# code...}
    }
    -
    ifif …If block - if (${1:condition}) {
    - ${0:# code...}
    }
    -
    ifelseif … else …If Else block - if (${1:condition}) {
    - ${2:# code...}
    } else {
    - ${3:# code...}
    }
    $0
    -
    if?$… = ( … ) ? … : …Ternary conditional assignment - $${1:retVal} = (${2:condition}) ? ${3:a} : ${4:b} ;
    -
    elseelse …Else block - else {
    - ${0:# code...}
    }
    -
    elseifelseif …Elseif block - elseif (${1:condition}) {
    - ${0:# code...}
    }
    -
    forfor …For-loop - for ($${1:i}=${2:0}; $${1:i} < $3; $${1:i}++) {
    - ${0:# code...}
    }
    -
    foreachforeach …Foreach loop - foreach ($${1:variable} as $${2:key} ${3:=> $${4:value}}) - {
    - ${0:# code...}
    }
    -
    array$… = array (…)Array initializer - $${1:arrayName} = array('$2' => $3${4:,} $0);
    -
    shorray$… = […]Array initializer - $${1:arrayName} = ['$2' => $3${4:,} $0];
    -
    keyval… => …Key-Value initializer - '$1' => $2${3:,} $0
    -
    switchswitch …Switch block - switch (\$${1:variable}) {
    - case '${2:value}':
    - ${3:# code...}
    - break;
    - $0
    - default:
    - ${4:# code...}
    - break;
    }
    -
    casecase …Case Block - case '${1:value}':
    - ${0:# code...}
    - break;
    -
    this$this->…$this->... - \$this->$0;
    -
    ethisecho $this->…Echo this - echo \$this->$0;
    -
    throwThrow ExceptionThrow exception - throw new $1Exception(${2:"${3:Error Processing - Request}"}${4:, ${5:1}});
    $0
    -
    #regionRegion StartFolding Region Start - #region
    -
    #endregionRegion EndFolding Region End - #endregion
    -
    tryTry Catch BlockTry catch block - try {
    - ${1://code...}
    } catch (${2:\Throwable} ${3:\$th}) {
    - ${4://throw \$th;}
    }
    -
    -
    -
    -

    Powershell

    - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    #regionRegion StartFolding Region Start - #region $0
    -
    #endregionRegion EndFolding Region End - #endregion
    -
    -
    -
    -

    Swift

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    printprintprint("...") - print("$1") $0
    -
    printvprint valueprint("\(...)") - print("\($1)") $0
    -
    whilewhilewhile statement - while ${1:condition} {
    - $0
    }
    -
    repeatrepeat-whilerepeat-while statement - repeat {
    - $0
    } while ${1:condition}
    -
    forforfor-in statement - for ${1:item} in ${2:collection} {
    - $0
    }
    -
    ififif statement - if ${1:condition} {
    - $0
    }
    -
    elifelse ifelse clause with a nested if statement - else if ${1:condition} {
    - $0
    }
    -
    elseelseelse clause - else {
    - $0
    }
    -
    ifletif letif statement with optional binding - if let ${1:value} = ${2:optional} {
    - $0
    }
    -
    guardguardguard statement - guard ${1:condition} else {
    - $0
    }
    -
    guardletguard letguard statement with optional binding - guard let ${1:value} = ${2:optional} else {
    - $0
    }
    -
    switchswitchswitch statement - switch ${1:value} {
    case ${2:pattern}:
    - $0
    default:
    -
    }
    -
    dododo statement - do {
    - $0
    } catch ${1:error} {
    - $2
    }
    -
    funcfuncfunction declaration - func ${1:name}(${2:parameters}) -> ${3:Type} {
    - $0
    }
    -
    structstructstruct declaration - struct ${1:Name} {

    - $0
    }
    -
    enumenumenum declaration - enum ${1:Name} {

    - case $0
    }
    -
    classclassclass declaration - class ${1:Name} {

    - $0
    }
    -
    protocolprotocolprotocol declaration - protocol ${1:Name} {

    - $0
    }
    -
    extensionextensionextension declaration - extension ${1:Type} {

    - $0
    }
    -
    -
    -
    -

    Typescript

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    ctorConstructorConstructor - /**
    - *
    - */
    constructor() {
    - super();
    - $0
    }
    -
    classClass DefinitionClass Definition - class ${1:name} {
    - constructor(${2:parameters}) {
    - $0
    - }
    }
    -
    public methodPublic Method DefinitionPublic Method Definition - /**
    - * ${1:name}
    - */
    public ${1:name}() {
    - $0
    }
    -
    private methodPrivate Method DefinitionPrivate Method Definition - private ${1:name}() {
    - $0
    }
    -
    import statementImport external module.Import external module. - import { $0 } from "${1:module}";
    -
    getProperty getterProperty getter -
    public get ${1:value}() : ${2:string} {
    - ${3:return $0}
    }

    -
    logLog to the consoleLog to the console - console.log($1);
    $0
    -
    warnLog warning to consoleLog warning to the console - console.warn($1);
    $0
    -
    errorLog error to consoleLog error to the console - console.error($1);
    $0
    -
    propDefine a full propertyDefine a full property -
    private _${1:value} : ${2:string};
    public get - ${1:value}() : ${2:string} {
    - return this._${1:value};
    }
    public set ${1:value}(v : - ${2:string}) {
    - this._${1:value} = v;
    }

    -
    refTriple-slash referenceTriple-slash reference - /// <reference path="$1" />
    $0
    -
    setProperty setterProperty setter -
    public set ${1:value}(v : ${2:string}) {
    - this.$3 = v;
    }

    -
    throwThrow ExceptionThrow Exception - throw new Error("$1");
    $0
    -
    forFor LoopFor Loop - for (let ${1:index} = 0; ${1:index} < ${2:array}.length; - ${1:index}++) {
    - const ${3:element} = ${2:array}[${1:index}];
    - $0
    }
    -
    foreach =>For-Each Loop using =>For-Each Loop using => - ${1:array}.forEach(${2:element} => {
    - $0
    });
    -
    forinFor-In LoopFor-In Loop - for (const ${1:key} in ${2:object}) {
    - if (Object.prototype.hasOwnProperty.call(${2:object}, - ${1:key})) {
    - const ${3:element} = ${2:object}[${1:key}];
    - $0
    - }
    }
    -
    forofFor-Of LoopFor-Of Loop - for (const ${1:iterator} of ${2:object}) {
    - $0
    }
    -
    forawaitofFor-Await-Of LoopFor-Await-Of Loop - for await (const ${1:iterator} of ${2:object}) {
    - $0
    }
    -
    functionFunction StatementFunction Statement - function ${1:name}(${2:params}:${3:type}) {
    - $0
    }
    -
    ifIf StatementIf Statement - if (${1:condition}) {
    - $0
    }
    -
    ifelseIf-Else StatementIf-Else Statement - if (${1:condition}) {
    - $0
    } else {
    -
    }
    -
    newNew StatementNew Statement - const ${1:name} = new ${2:type}(${3:arguments});$0
    -
    switchSwitch StatementSwitch Statement - switch (${1:key}) {
    - case ${2:value}:
    - $0
    - break;

    - default:
    - break;
    }
    -
    whileWhile StatementWhile Statement - while (${1:condition}) {
    - $0
    }
    -
    dowhileDo-While StatementDo-While Statement - do {
    - $0
    } while (${1:condition});
    -
    trycatchTry-Catch StatementTry-Catch Statement - try {
    - $0
    } catch (${1:error}) {
    -
    }
    -
    settimeoutSet Timeout FunctionSet Timeout Function - setTimeout(() => {
    - $0
    }, ${1:timeout});
    -
    #regionRegion StartFolding Region Start - //#region $0
    -
    #endregionRegion EndFolding Region End - //#endregion
    -
    newpromisenew PromiseCreate a new Promise - new Promise<$1:type>((resolve, reject) => {
    - $1
    })
    -
    async functionAsync Function StatementAsync Function Statement - async function ${1:name}(${2:params}:${3:type}) {
    - $0
    }
    -
    async arrow functionAsync Function ExpressionAsync Function Expression - async (${1:params}:${2:type}) => {
    - $0
    }
    -
    -
    -
    -

    VB

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PrefixNameDescriptionBody
    forFor Next LoopFor Next Loop - For ${1:index} As ${2:ObjectType} = ${3:lower} To - ${4:Upper}
    - $0
    Next ${1:index}
    -
    foreFor Each...NextFor Each...Next - For Each ${1:Variable} As ${2:ObjectType} In - ${3:Collection}
    - $0
    Next
    -
    foriFor i...Next iFor i...Next i - For i As ${1:Integer} = ${2:Lower} To ${3:Upper}
    - $0
    Next i
    -
    forjFor j...Next jFor j...Next j - For j As ${1:Integer} = ${2:Lower} To ${3:Upper}
    - $0
    Next j
    -
    pfPublic Function...Public Function... - Public Function ${1:FunctionName}(${2:ParameterList}) As - ${3:ReturnType}
    - Try
    - $0
    - Catch ex As Exception
    - End Try
    - Return ${3:ReturnValue}
    End Function
    -
    psPublic Sub ...Public Sub ... - Public Sub ${1:ProcedureName}(${2:ParameterList})
    - Try
    - $0
    - Catch ex As Exception
    - End Try
    End Sub
    -
    whileWhile ... End WhileWhile ... End While - While ${1:Boolean}
    - $0
    End While
    -
    #RegionRegion StartFolding Region Start - #Region $0
    -
    #End RegionRegion EndFolding Region End - #End Region
    -
    -
    -
    - - Go to top - - - - - - - diff --git a/todo.md b/todo.md index c3d15ea..6f48fb6 100644 --- a/todo.md +++ b/todo.md @@ -1,9 +1,9 @@ # To Do -1. Test multi-root workspace for workspace snippets. -1. Add formatting of `scope` content to ensure consistent formatting. If no spaces between words values, add one after the comma. -1. Is the `scope` field ever in a snippets file in an extension? -1. Refactor `language` field in *snippet-collection.js*. It only applies to user snippets if I remember correctly. +## Changes to consider + +1. Support multi-root workspaces. For multi-root workspaces, a sub workspace can have its own snippets in its .vscode folder. You would need to look at the `.code-workspace` to discover the sub workspaces. 1. This snippet extension - https://open-vsx.org/extension/hollowtree/vue-snippets - appears to cause an error. -1. Refactor Extensions make more comprehensible. Particularly code around extension-related snippets and the view. 1. Show the shortcuts assigned to any snippets (via command 'insert snippet')? + +$statement = $this->pdo->prepare($sql); diff --git a/webpack.config.js b/webpack.config.js index f8ecd25..5ed6c67 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -6,11 +6,12 @@ const TerserPlugin = require("terser-webpack-plugin"); const crypto = require("crypto"); const crypto_orig_createHash = crypto.createHash; -crypto.createHash = algorithm => crypto_orig_createHash(algorithm === "md4" ? "sha256" : algorithm); +crypto.createHash = (algorithm) => + crypto_orig_createHash(algorithm === "md4" ? "sha256" : algorithm); const config = { target: "node", - entry: { main: "./src/extension.js" }, + entry: { main: "./src/main.js" }, optimization: { minimizer: [new OptimizeCSSAssetsPlugin(), new TerserPlugin()], }, @@ -22,7 +23,7 @@ const config = { }, output: { path: path.resolve(__dirname, "dist"), - filename: "extension.js", + filename: "main.js", libraryTarget: "commonjs2", devtoolModuleFilenameTemplate: "../[resource-path]", },