Initial commit for myTemplateGenerator extension, including core functionality for template-based file and folder generation, localization support, and configuration options. Added essential files such as package.json, README.md, and TypeScript configuration, along with necessary dependencies and build configurations.

This commit is contained in:
S.Gromov
2025-07-13 18:33:25 +03:00
commit 80350e8f5f
15 changed files with 6423 additions and 0 deletions

133
.gitignore vendored Normal file
View File

@@ -0,0 +1,133 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
.vscode/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
.cache
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
.DS_Store

5
.vscode-test.mjs Normal file
View File

@@ -0,0 +1,5 @@
import { defineConfig } from '@vscode/test-cli';
export default defineConfig({
files: 'out/test/**/*.test.js',
});

14
.vscodeignore Normal file
View File

@@ -0,0 +1,14 @@
.vscode/**
.vscode-test/**
out/**
node_modules/**
src/**
.gitignore
.yarnrc
webpack.config.js
vsc-extension-quickstart.md
**/tsconfig.json
**/eslint.config.mjs
**/*.map
**/*.ts
**/.vscode-test.*

9
CHANGELOG.md Normal file
View File

@@ -0,0 +1,9 @@
# Change Log
All notable changes to the "mytemplategenerator" extension will be documented in this file.
Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
## [Unreleased]
- Initial release

191
README.md Normal file
View File

@@ -0,0 +1,191 @@
# myTemplateGenerator
[English](#english) | [Русский](#русский)
---
# English
## myTemplateGenerator — Template-based structure generation for VSCode
**Features:**
- Syntax highlighting and autocomplete for template variables in templates
- Generate files and folders from templates with variable substitution
- Flexible configuration via `mytemplategenerator.json` or visual configurator
- Full localization (English/Russian) for all UI, messages, and menus
- Choose variable input mode: Webview (form) or inputBox (one by one)
- Overwrite control: allow or forbid overwriting existing files/folders
- Smart conflict handling: clear notifications if structure already exists
- **No Handlebars dependency**: variable substitution is handled by the extension itself
### Quick Start
1. Create a `templates` folder in your project root.
2. Add subfolders for different templates (e.g., `components`, `store`).
3. Use variables like `{{name}}` or `{{name.pascalCase}}` in file/folder names and file contents.
4. Right-click a folder in VSCode and select **Create from template...**
5. Choose a template, fill in variables, and click "Create".
### Example template structure
```
templates/
components/
{{name}}/
index.js
style.module.css
store/
{{name}}Store.js
```
### Supported variables and modifiers
You can use variables with modifiers via dot notation:
- `{{name}}` — as entered by user
- `{{name.pascalCase}}` — PascalCase
- `{{name.camelCase}}` — camelCase
- `{{name.snakeCase}}` — snake_case
- `{{name.kebabCase}}` — kebab-case
- `{{name.screamingSnakeCase}}` — SCREAMING_SNAKE_CASE
- `{{name.upperCase}}` — First letter uppercase
- `{{name.lowerCase}}` — all lowercase
- `{{name.upperCaseAll}}` — ALLUPPERCASE (no separators)
- `{{name.lowerCaseAll}}` — alllowercase (no separators)
> When searching for variables for the form, only the name before the dot is considered. For example, `{{name}}` and `{{name.pascalCase}}` are the same variable.
### Example usage in template
```
components/
{{name.pascalCase}}/
index.js
{{name.camelCase}}.service.js
{{name.snakeCase}}.test.js
```
And in file contents:
```
export class {{name.pascalCase}} {}
const name = '{{name}}';
```
### Configuration
Use `mytemplategenerator.json` in your project root or the visual configurator (**Configure myTemplateGenerator...**):
```json
{
"templatesPath": "templates",
"overwriteFiles": false,
"inputMode": "webview", // or "inputBox"
"language": "en" // or "ru"
}
```
- **templatesPath** — path to templates folder
- **overwriteFiles** — allow or forbid overwriting existing files/folders
- **inputMode** — variable input mode: "webview" (form) or "inputBox" (one by one)
- **language** — plugin UI language (en/ru)
### Localization
- All UI, messages, errors, and menus are localized.
- Webview and messages use the language from config.
- Menu/command language depends on VSCode interface language.
### Key commands
- **Create from template...** — generate structure (context menu)
- **Configure myTemplateGenerator...** — open visual configurator (command palette)
### Error handling & overwrite
- If structure or file exists and overwrite is forbidden, generation is cancelled and a clear notification is shown.
- Any file creation error stops generation and shows the reason.
---
# Русский
## myTemplateGenerator — Генерация структуры из шаблонов для VSCode
**Возможности:**
- Подсветка синтаксиса и автокомплит переменных в шаблонах
- Генерация файлов и папок по шаблонам с подстановкой переменных
- Гибкая настройка через `mytemplategenerator.json` или визуальный конфигуратор
- Полная локализация (русский/английский) для всего интерфейса, сообщений и меню
- Выбор способа ввода переменных: Webview (форма) или inputBox (по одной)
- Контроль перезаписи: можно запретить или разрешить перезапись существующих файлов/папок
- Умная обработка конфликтов: понятные уведомления, если структура уже существует
- **Без зависимости от Handlebars**: подстановка переменных реализована внутри расширения
### Быстрый старт
1. В корне проекта создайте папку `templates`.
2. Внутри неё создайте подпапки для разных шаблонов (например, `components`, `store`).
3. Внутри шаблонов используйте переменные вида `{{name}}` или `{{name.pascalCase}}` в именах файлов/папок и в содержимом файлов.
4. Кликните правой кнопкой мыши на нужной папке в VSCode и выберите пункт **Создать из шаблона...**
5. В появившемся окне выберите шаблон, заполните переменные и нажмите "Создать".
### Пример структуры шаблонов
```
templates/
components/
{{name}}/
index.js
style.module.css
store/
{{name}}Store.js
```
### Переменные и модификаторы
В шаблонах можно использовать переменные с модификаторами через точку:
- `{{name}}` — как ввёл пользователь
- `{{name.pascalCase}}` — PascalCase
- `{{name.camelCase}}` — camelCase
- `{{name.snakeCase}}` — snake_case
- `{{name.kebabCase}}` — kebab-case
- `{{name.screamingSnakeCase}}` — SCREAMING_SNAKE_CASE
- `{{name.upperCase}}` — Первая буква большая
- `{{name.lowerCase}}` — все буквы маленькие
- `{{name.upperCaseAll}}`ВСЕ БУКВЫ БОЛЬШИЕ (без разделителей)
- `{{name.lowerCaseAll}}` — все буквы маленькие (без разделителей)
> При поиске переменных для формы учитывается только имя до точки. Например, `{{name}}` и `{{name.pascalCase}}` — это одна переменная.
### Пример использования в шаблоне
```
components/
{{name.pascalCase}}/
index.js
{{name.camelCase}}.service.js
{{name.snakeCase}}.test.js
```
Внутри файлов также можно использовать эти переменные:
```
export class {{name.pascalCase}} {}
const name = '{{name}}';
```
### Конфигурация
Для гибкой настройки используйте файл `mytemplategenerator.json` в корне проекта или визуальный конфигуратор (команда **Настроить myTemplateGenerator...**):
```json
{
"templatesPath": "templates",
"overwriteFiles": false,
"inputMode": "webview", // или "inputBox"
"language": "ru" // или "en"
}
```
- **templatesPath** — путь к папке с шаблонами
- **overwriteFiles** — разрешать ли перезапись существующих файлов/папок
- **inputMode** — способ ввода переменных: "webview" (форма) или "inputBox" (по одной)
- **language** — язык интерфейса плагина (ru/en)
### Локализация
- Все сообщения, Webview, ошибки и пункты меню локализованы.
- Язык Webview и сообщений выбирается в конфигураторе.
- Язык пунктов меню и команд зависит от языка интерфейса VSCode.
### Важные команды
- **Создать из шаблона...** — генерация структуры (контекстное меню)
- **Настроить myTemplateGenerator...** — открыть визуальный конфигуратор (палитра команд)
### Обработка ошибок и перезаписи
- Если структура или файл уже существуют и перезапись запрещена, генерация не выполняется и выводится понятное уведомление.
- Если при создании любого файла возникает ошибка — генерация полностью прекращается, и пользователь видит причину.
---

28
eslint.config.mjs Normal file
View File

@@ -0,0 +1,28 @@
import typescriptEslint from "@typescript-eslint/eslint-plugin";
import tsParser from "@typescript-eslint/parser";
export default [{
files: ["**/*.ts"],
}, {
plugins: {
"@typescript-eslint": typescriptEslint,
},
languageOptions: {
parser: tsParser,
ecmaVersion: 2022,
sourceType: "module",
},
rules: {
"@typescript-eslint/naming-convention": ["warn", {
selector: "import",
format: ["camelCase", "PascalCase"],
}],
curly: "warn",
eqeqeq: "warn",
"no-throw-literal": "warn",
semi: "warn",
},
}];

4679
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

85
package.json Normal file
View File

@@ -0,0 +1,85 @@
{
"name": "mytemplategenerator",
"displayName": "myTemplateGenerator",
"description": "Generate files and folders from customizable templates with variable substitution in VSCode.",
"version": "0.0.1",
"author": "Sergey Gromov",
"url": "https://github.com/gormov1122/MyTemplateGenerator",
"engines": {
"vscode": "^1.60.0"
},
"categories": [
"Other"
],
"activationEvents": [
"onStartupFinished",
"onLanguage:javascript",
"onLanguage:typescript",
"onLanguage:css",
"onLanguage:plaintext",
"onFileSystem: file"
],
"main": "./dist/extension.js",
"contributes": {
"commands": [
{
"command": "mytemplategenerator.createFromTemplate",
"title": "%mytemplategenerator.createFromTemplate.title%"
},
{
"command": "mytemplategenerator.configure",
"title": "%mytemplategenerator.configure.title%"
}
],
"menus": {
"explorer/context": [
{
"command": "mytemplategenerator.createFromTemplate",
"group": "navigation@10"
}
]
},
"semanticTokenColors": [
{
"token": "bracket",
"foreground": "#FFA500"
},
{
"token": "variable",
"foreground": "#4EC900"
},
{
"token": "modifier",
"foreground": "#0074D9"
}
]
},
"scripts": {
"vscode:prepublish": "npm run package",
"compile": "webpack",
"watch": "webpack --watch",
"package": "webpack --mode production --devtool hidden-source-map",
"compile-tests": "tsc -p . --outDir out",
"watch-tests": "tsc -p . -w --outDir out",
"pretest": "npm run compile-tests && npm run compile && npm run lint",
"lint": "eslint src",
"test": "vscode-test"
},
"devDependencies": {
"@types/mocha": "^10.0.10",
"@types/node": "20.x",
"@types/vscode": "^1.102.0",
"@typescript-eslint/eslint-plugin": "^8.31.1",
"@typescript-eslint/parser": "^8.31.1",
"@vscode/test-cli": "^0.0.11",
"@vscode/test-electron": "^2.5.2",
"eslint": "^9.25.1",
"ts-loader": "^9.5.2",
"typescript": "^5.8.3",
"webpack": "^5.99.7",
"webpack-cli": "^6.0.1"
},
"dependencies": {
"handlebars": "^4.7.8"
}
}

4
package.nls.json Normal file
View File

@@ -0,0 +1,4 @@
{
"mytemplategenerator.createFromTemplate.title": "Create from template...",
"mytemplategenerator.configure.title": "Configure myTemplateGenerator..."
}

4
package.nls.ru.json Normal file
View File

@@ -0,0 +1,4 @@
{
"mytemplategenerator.createFromTemplate.title": "Создать из шаблона...",
"mytemplategenerator.configure.title": "Настроить myTemplateGenerator..."
}

1086
src/extension.ts Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,73 @@
import * as assert from 'assert';
// You can import and use all API from the 'vscode' module
// as well as import your extension to test it
import * as vscode from 'vscode';
import {
toPascalCase,
toCamelCase,
toSnakeCase,
toKebabCase,
toScreamingSnakeCase,
toUpperCaseFirst,
toUpperCaseAll,
toLowerCaseAll,
buildVarsObject,
CASE_MODIFIERS
} from '../extension';
suite('Extension Test Suite', () => {
vscode.window.showInformationMessage('Start all tests.');
test('Sample test', () => {
assert.strictEqual(-1, [1, 2, 3].indexOf(5));
assert.strictEqual(-1, [1, 2, 3].indexOf(0));
});
});
suite('Template Variable Modifiers', () => {
const input = 'my super-name';
test('toPascalCase', () => {
assert.strictEqual(toPascalCase(input), 'MySuperName');
});
test('toCamelCase', () => {
assert.strictEqual(toCamelCase(input), 'mySuperName');
});
test('toSnakeCase', () => {
assert.strictEqual(toSnakeCase(input), 'my_super_name');
});
test('toKebabCase', () => {
assert.strictEqual(toKebabCase(input), 'my-super-name');
});
test('toScreamingSnakeCase', () => {
assert.strictEqual(toScreamingSnakeCase(input), 'MY_SUPER_NAME');
});
test('toUpperCaseFirst', () => {
assert.strictEqual(toUpperCaseFirst(input), 'My super-name');
});
test('toUpperCaseAll', () => {
assert.strictEqual(toUpperCaseAll(input), 'MYSUPERNAME');
});
test('toLowerCaseAll', () => {
assert.strictEqual(toLowerCaseAll(input), 'mysupername');
});
test('CASE_MODIFIERS map covers all', () => {
for (const [mod, fn] of Object.entries(CASE_MODIFIERS)) {
assert.strictEqual(typeof fn(input), 'string');
}
});
test('buildVarsObject generates all keys', () => {
const vars = buildVarsObject({ name: input });
assert.strictEqual(vars['name'], input);
assert.strictEqual(vars['name.pascalCase'], 'MySuperName');
assert.strictEqual(vars['name.camelCase'], 'mySuperName');
assert.strictEqual(vars['name.snakeCase'], 'my_super_name');
assert.strictEqual(vars['name.kebabCase'], 'my-super-name');
assert.strictEqual(vars['name.screamingSnakeCase'], 'MY_SUPER_NAME');
assert.strictEqual(vars['name.upperCase'], 'My super-name');
assert.strictEqual(vars['name.lowerCase'], 'my super-name');
assert.strictEqual(vars['name.upperCaseAll'], 'MYSUPERNAME');
assert.strictEqual(vars['name.lowerCaseAll'], 'mysupername');
});
});

16
tsconfig.json Normal file
View File

@@ -0,0 +1,16 @@
{
"compilerOptions": {
"module": "Node16",
"target": "ES2022",
"lib": [
"ES2022"
],
"sourceMap": true,
"rootDir": "src",
"strict": true, /* enable all strict type-checking options */
/* Additional Checks */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
}
}

View File

@@ -0,0 +1,48 @@
# Welcome to your VS Code Extension
## What's in the folder
* This folder contains all of the files necessary for your extension.
* `package.json` - this is the manifest file in which you declare your extension and command.
* The sample plugin registers a command and defines its title and command name. With this information VS Code can show the command in the command palette. It doesnt yet need to load the plugin.
* `src/extension.ts` - this is the main file where you will provide the implementation of your command.
* The file exports one function, `activate`, which is called the very first time your extension is activated (in this case by executing the command). Inside the `activate` function we call `registerCommand`.
* We pass the function containing the implementation of the command as the second parameter to `registerCommand`.
## Setup
* install the recommended extensions (amodio.tsl-problem-matcher, ms-vscode.extension-test-runner, and dbaeumer.vscode-eslint)
## Get up and running straight away
* Press `F5` to open a new window with your extension loaded.
* Run your command from the command palette by pressing (`Ctrl+Shift+P` or `Cmd+Shift+P` on Mac) and typing `Hello World`.
* Set breakpoints in your code inside `src/extension.ts` to debug your extension.
* Find output from your extension in the debug console.
## Make changes
* You can relaunch the extension from the debug toolbar after changing code in `src/extension.ts`.
* You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes.
## Explore the API
* You can open the full set of our API when you open the file `node_modules/@types/vscode/index.d.ts`.
## Run tests
* Install the [Extension Test Runner](https://marketplace.visualstudio.com/items?itemName=ms-vscode.extension-test-runner)
* Run the "watch" task via the **Tasks: Run Task** command. Make sure this is running, or tests might not be discovered.
* Open the Testing view from the activity bar and click the Run Test" button, or use the hotkey `Ctrl/Cmd + ; A`
* See the output of the test result in the Test Results view.
* Make changes to `src/test/extension.test.ts` or create new test files inside the `test` folder.
* The provided test runner will only consider files matching the name pattern `**.test.ts`.
* You can create folders inside the `test` folder to structure your tests any way you want.
## Go further
* Reduce the extension size and improve the startup time by [bundling your extension](https://code.visualstudio.com/api/working-with-extensions/bundling-extension).
* [Publish your extension](https://code.visualstudio.com/api/working-with-extensions/publishing-extension) on the VS Code extension marketplace.
* Automate builds by setting up [Continuous Integration](https://code.visualstudio.com/api/working-with-extensions/continuous-integration).

48
webpack.config.js Normal file
View File

@@ -0,0 +1,48 @@
//@ts-check
'use strict';
const path = require('path');
//@ts-check
/** @typedef {import('webpack').Configuration} WebpackConfig **/
/** @type WebpackConfig */
const extensionConfig = {
target: 'node', // VS Code extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/
mode: 'none', // this leaves the source code as close as possible to the original (when packaging we set this to 'production')
entry: './src/extension.ts', // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/
output: {
// the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/
path: path.resolve(__dirname, 'dist'),
filename: 'extension.js',
libraryTarget: 'commonjs2'
},
externals: {
vscode: 'commonjs vscode' // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/
// modules added here also need to be added in the .vscodeignore file
},
resolve: {
// support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader
extensions: ['.ts', '.js']
},
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
use: [
{
loader: 'ts-loader'
}
]
}
]
},
devtool: 'nosources-source-map',
infrastructureLogging: {
level: "log", // enables logging required for problem matchers
},
};
module.exports = [ extensionConfig ];