Update package version to 0.0.8, add new configuration options for templates path, file overwrite behavior, input mode, and language selection. Remove old .vsix files and update README for improved usage instructions.

This commit is contained in:
S.Gromov
2025-07-15 09:22:48 +03:00
parent bcb2c381fb
commit 0842268f28
14 changed files with 82 additions and 58 deletions

2
.gitignore vendored
View File

@@ -130,3 +130,5 @@ dist
.pnp.* .pnp.*
.DS_Store .DS_Store
*.vsix

View File

@@ -13,14 +13,14 @@
![Logo](https://raw.githubusercontent.com/gormov1122/MyTemplateGenerator/main/src/images/3.png) ![Logo](https://raw.githubusercontent.com/gormov1122/MyTemplateGenerator/main/src/images/3.png)
**How to use:** **How to use:**
1. Create a folder with templates (default: `templates`). 1. Create a folder with templates (default: `.templates`).
2. Use variables in templates: `{{name}}`, `{{name.pascalCase}}`, etc. 2. Use variables in templates: `{{name}}`, `{{name.pascalCase}}`, etc.
3. Right-click any folder in your project → **Create from template...** 3. Right-click any folder in your project → **Create from template...**
4. Select a template, fill in variables — the structure is generated automatically. 4. Select a template, fill in variables — the structure is generated automatically.
**Example template:** **Example template:**
``` ```
templates/ .templates/
component/ component/
{{name}}/ {{name}}/
index.tsx index.tsx
@@ -62,10 +62,12 @@ This extension works with **any framework** — you define your own templates fo
Just create a template for your favorite stack — and generate any structure you want! 🎉 Just create a template for your favorite stack — and generate any structure you want! 🎉
**Configuration:** **Configuration:**
All settings via `mycodegenerate.json` in the project root or the visual configurator. All settings are managed via the standard VSCode user settings (or the visual configurator).
To open the settings menu, press <kbd>Ctrl</kbd>+<kbd>P</kbd>, type `Configure myTemplateGenerator...` and select the menu item. To open the settings menu, press <kbd>Ctrl</kbd>+<kbd>P</kbd>, type `Configure myTemplateGenerator...` and select the menu item.
You can also find all options in VSCode settings under `myTemplateGenerator`.
# MyTemplateGenerator (русский) # MyTemplateGenerator (русский)
@@ -80,14 +82,14 @@ To open the settings menu, press <kbd>Ctrl</kbd>+<kbd>P</kbd>, type `Configure m
![Logo](https://raw.githubusercontent.com/gormov1122/MyTemplateGenerator/main/src/images/3.png) ![Logo](https://raw.githubusercontent.com/gormov1122/MyTemplateGenerator/main/src/images/3.png)
**Как использовать:** **Как использовать:**
1. Создайте папку с шаблонами (по умолчанию `templates`). 1. Создайте папку с шаблонами (по умолчанию `.templates`).
2. Используйте переменные в шаблонах: `{{name}}`, `{{name.pascalCase}}` и т.д. 2. Используйте переменные в шаблонах: `{{name}}`, `{{name.pascalCase}}` и т.д.
3. Кликните правой кнопкой по папке в проекте → **Создать из шаблона...** 3. Кликните правой кнопкой по папке в проекте → **Создать из шаблона...**
4. Выберите шаблон, заполните переменные — структура будет создана автоматически. 4. Выберите шаблон, заполните переменные — структура будет создана автоматически.
**Пример шаблона:** **Пример шаблона:**
``` ```
templates/ .templates/
component/ component/
{{name}}/ {{name}}/
index.tsx index.tsx
@@ -129,6 +131,8 @@ templates/
Создайте шаблон под свой стек — и генерируйте любые структуры! 🎉 Создайте шаблон под свой стек — и генерируйте любые структуры! 🎉
**Настройка:** **Настройка:**
Всё настраивается через файл `mycodegenerate.json` в корне проекта или визуальный конфигуратор. Все параметры задаются через стандартные пользовательские настройки VSCode (или визуальный конфигуратор).
Чтобы открыть меню настроек, нажмите <kbd>Ctrl</kbd>+<kbd>P</kbd>, введите `Настроить myTemplateGenerator...` (или `Configure myTemplateGenerator...` для английского интерфейса) и выберите соответствующий пункт. Чтобы открыть меню настроек, нажмите <kbd>Ctrl</kbd>+<kbd>P</kbd>, введите `Настроить myTemplateGenerator...` (или `Configure myTemplateGenerator...` для английского интерфейса) и выберите соответствующий пункт.
Также вы можете найти все параметры в настройках VSCode по ключу `myTemplateGenerator`.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -2,7 +2,7 @@
"name": "mytemplategenerator", "name": "mytemplategenerator",
"displayName": "myTemplateGenerator", "displayName": "myTemplateGenerator",
"description": "Generate files and folders from customizable templates with variable substitution in VSCode.", "description": "Generate files and folders from customizable templates with variable substitution in VSCode.",
"version": "0.0.7", "version": "0.0.8",
"publisher": "MyTemplateGenerator", "publisher": "MyTemplateGenerator",
"author": "Sergey Gromov", "author": "Sergey Gromov",
"icon": "logo.png", "icon": "logo.png",
@@ -41,6 +41,41 @@
} }
] ]
}, },
"configuration": {
"title": "myTemplateGenerator",
"properties": {
"myTemplateGenerator.templatesPath": {
"type": "string",
"default": ".templates",
"description": "%mytemplategenerator.config.templatesPath.description%",
"markdownDescription": "%mytemplategenerator.config.templatesPath.description%",
"scope": "application"
},
"myTemplateGenerator.overwriteFiles": {
"type": "boolean",
"default": false,
"description": "%mytemplategenerator.config.overwriteFiles.description%",
"markdownDescription": "%mytemplategenerator.config.overwriteFiles.description%",
"scope": "application"
},
"myTemplateGenerator.inputMode": {
"type": "string",
"enum": ["webview", "inputBox"],
"default": "webview",
"description": "%mytemplategenerator.config.inputMode.description%",
"markdownDescription": "%mytemplategenerator.config.inputMode.description%",
"scope": "application"
},
"myTemplateGenerator.language": {
"type": "string",
"enum": ["ru", "en"],
"default": "en",
"description": "%mytemplategenerator.config.language.description%",
"markdownDescription": "%mytemplategenerator.config.language.description%",
"scope": "application"
}
}
},
"semanticTokenColors": [ "semanticTokenColors": [
{ {
"token": "bracket", "token": "bracket",

View File

@@ -1,4 +1,8 @@
{ {
"mytemplategenerator.createFromTemplate.title": "Create from template...", "mytemplategenerator.createFromTemplate.title": "Create from template...",
"mytemplategenerator.configure.title": "Configure myTemplateGenerator..." "mytemplategenerator.configure.title": "Configure myTemplateGenerator...",
"mytemplategenerator.config.templatesPath.description": "Path to the templates folder (relative to the project root)",
"mytemplategenerator.config.overwriteFiles.description": "Overwrite existing files when generating from template",
"mytemplategenerator.config.inputMode.description": "Variable input mode: webview or inputBox",
"mytemplategenerator.config.language.description": "Extension interface language"
} }

View File

@@ -1,4 +1,8 @@
{ {
"mytemplategenerator.createFromTemplate.title": "Создать из шаблона...", "mytemplategenerator.createFromTemplate.title": "Создать из шаблона...",
"mytemplategenerator.configure.title": "Настроить myTemplateGenerator..." "mytemplategenerator.configure.title": "Настроить myTemplateGenerator...",
"mytemplategenerator.config.templatesPath.description": "Путь к папке с шаблонами (относительно корня проекта)",
"mytemplategenerator.config.overwriteFiles.description": "Перезаписывать ли существующие файлы при генерации",
"mytemplategenerator.config.inputMode.description": "Режим ввода переменных: webview или inputBox",
"mytemplategenerator.config.language.description": "Язык интерфейса расширения"
} }

View File

@@ -10,29 +10,28 @@ export interface MyTemplateGeneratorConfig {
language?: string; language?: string;
} }
export function getConfigPath(): string | undefined {
const folders = vscode.workspace.workspaceFolders;
if (!folders || folders.length === 0) return undefined;
return path.join(folders[0].uri.fsPath, 'mycodegenerate.json');
}
export function readConfig(): MyTemplateGeneratorConfig { export function readConfig(): MyTemplateGeneratorConfig {
const configPath = getConfigPath(); const config = vscode.workspace.getConfiguration('myTemplateGenerator');
if (configPath && fs.existsSync(configPath)) {
const raw = fs.readFileSync(configPath, 'utf8');
return JSON.parse(raw);
}
// Значения по умолчанию
return { return {
templatesPath: 'templates', templatesPath: config.get<string>('templatesPath', '.templates'),
overwriteFiles: false, overwriteFiles: config.get<boolean>('overwriteFiles', false),
inputMode: 'inputBox', inputMode: config.get<'webview' | 'inputBox'>('inputMode', 'webview'),
language: 'en', language: config.get<string>('language', 'en'),
}; };
} }
export function writeConfig(config: MyTemplateGeneratorConfig) { export async function writeConfig(newConfig: Partial<MyTemplateGeneratorConfig>) {
const configPath = getConfigPath(); const config = vscode.workspace.getConfiguration('myTemplateGenerator');
if (!configPath) return; if (newConfig.templatesPath !== undefined) {
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8'); await config.update('templatesPath', newConfig.templatesPath, vscode.ConfigurationTarget.Global);
}
if (newConfig.overwriteFiles !== undefined) {
await config.update('overwriteFiles', newConfig.overwriteFiles, vscode.ConfigurationTarget.Global);
}
if (newConfig.inputMode !== undefined) {
await config.update('inputMode', newConfig.inputMode, vscode.ConfigurationTarget.Global);
}
if (newConfig.language !== undefined) {
await config.update('language', newConfig.language, vscode.ConfigurationTarget.Global);
}
} }

View File

@@ -41,7 +41,6 @@ export function activate(context: vscode.ExtensionContext) {
// Use the console to output diagnostic information (console.log) and errors (console.error) // Use the console to output diagnostic information (console.log) and errors (console.error)
// This line of code will only be executed once when your extension is activated // This line of code will only be executed once when your extension is activated
console.log('Congratulations, your extension "mytemplategenerator" is now active!');
// The command has been defined in the package.json file // The command has been defined in the package.json file
// Now provide the implementation of the command with registerCommand // Now provide the implementation of the command with registerCommand
@@ -56,25 +55,20 @@ export function activate(context: vscode.ExtensionContext) {
const config = readConfig(); const config = readConfig();
const dict = I18N_DICTIONARIES[config.language || 'ru'] || I18N_DICTIONARIES['ru']; const dict = I18N_DICTIONARIES[config.language || 'ru'] || I18N_DICTIONARIES['ru'];
const workspaceFolders = vscode.workspace.workspaceFolders; const workspaceFolders = vscode.workspace.workspaceFolders;
console.log('[DEBUG] Запуск команды createFromTemplate');
if (!workspaceFolders || workspaceFolders.length === 0) { if (!workspaceFolders || workspaceFolders.length === 0) {
vscode.window.showErrorMessage(dict.noFolders); vscode.window.showErrorMessage(dict.noFolders);
console.log('[DEBUG] Нет открытых папок рабочего пространства');
return; return;
} }
const templatesDir = path.join(workspaceFolders[0].uri.fsPath, config.templatesPath); const templatesDir = path.join(workspaceFolders[0].uri.fsPath, config.templatesPath);
if (!fs.existsSync(templatesDir) || !fs.statSync(templatesDir).isDirectory()) { if (!fs.existsSync(templatesDir) || !fs.statSync(templatesDir).isDirectory()) {
vscode.window.showErrorMessage(`${dict.templatesNotFound} ${templatesDir}`); vscode.window.showErrorMessage(`${dict.templatesNotFound} ${templatesDir}`);
console.log('[DEBUG] Папка шаблонов не найдена:', templatesDir);
return; return;
} }
let template: string | undefined; let template: string | undefined;
let userVars: Record<string, string> | undefined; let userVars: Record<string, string> | undefined;
if (config.inputMode === 'webview') { if (config.inputMode === 'webview') {
vscode.window.showInformationMessage('[DEBUG] Вызов webview создания шаблона...'); vscode.window.showInformationMessage('[DEBUG] Вызов webview создания шаблона...');
console.log('[DEBUG] Вызов showTemplateAndVarsWebview', { templatesDir, uri: uri.fsPath, lang: config.language });
const result: { template: string, vars: Record<string, string> } | undefined = await showTemplateAndVarsWebview(context, templatesDir, uri.fsPath, config.language || 'ru'); const result: { template: string, vars: Record<string, string> } | undefined = await showTemplateAndVarsWebview(context, templatesDir, uri.fsPath, config.language || 'ru');
console.log('[DEBUG] Результат showTemplateAndVarsWebview:', result);
if (!result) { if (!result) {
vscode.window.showInformationMessage('[DEBUG] Webview был закрыт или не вернул результат'); vscode.window.showInformationMessage('[DEBUG] Webview был закрыт или не вернул результат');
return; return;
@@ -104,7 +98,6 @@ export function activate(context: vscode.ExtensionContext) {
copyTemplateWithVars(templateDir, uri.fsPath, vars, config.overwriteFiles, dict, template); copyTemplateWithVars(templateDir, uri.fsPath, vars, config.overwriteFiles, dict, template);
} catch (e: any) { } catch (e: any) {
vscode.window.showErrorMessage(`${dict.createError}: ${e.message}`); vscode.window.showErrorMessage(`${dict.createError}: ${e.message}`);
console.log('[DEBUG] Ошибка при копировании шаблона:', e);
} }
}); });
@@ -121,22 +114,7 @@ export function activate(context: vscode.ExtensionContext) {
clearDiagnosticsForTemplates(context); // <--- Очищаем diagnostics для шаблонов clearDiagnosticsForTemplates(context); // <--- Очищаем diagnostics для шаблонов
// === Отслеживание изменений конфига === // === Отслеживание изменений конфига ===
const workspaceFolders = vscode.workspace.workspaceFolders; // (Удалено: теперь все настройки глобальные через VSCode settings)
if (workspaceFolders && workspaceFolders.length > 0) {
const configPath = path.join(workspaceFolders[0].uri.fsPath, 'mycodegenerate.json');
if (fs.existsSync(configPath)) {
fs.watch(configPath, { persistent: false }, (eventType) => {
if (eventType === 'change' || eventType === 'rename') {
// Перерегистрируем провайдер подсветки
if (semanticHighlightDisposable) {
semanticHighlightDisposable.dispose();
}
semanticHighlightDisposable = registerTemplateSemanticHighlight(context);
console.log('[DEBUG] Провайдер семантической подсветки перерегистрирован после изменения конфига');
}
});
}
}
} }
// This method is called when your extension is deactivated // This method is called when your extension is deactivated

View File

@@ -20,8 +20,6 @@ export function registerTemplateSemanticHighlight(context: vscode.ExtensionConte
const workspaceFolders = vscode.workspace.workspaceFolders; const workspaceFolders = vscode.workspace.workspaceFolders;
if (!workspaceFolders || workspaceFolders.length === 0) return; if (!workspaceFolders || workspaceFolders.length === 0) return;
const templatesDir = path.join(workspaceFolders[0].uri.fsPath, templatesPath); const templatesDir = path.join(workspaceFolders[0].uri.fsPath, templatesPath);
console.log('[DEBUG] semantic tokens called for', document.uri.fsPath);
console.log('[DEBUG] Проверка шаблонной папки:', document.uri.fsPath, templatesDir, isInTemplatesDir(document.uri.fsPath, templatesDir));
// Проверяем, что файл в папке шаблонов // Проверяем, что файл в папке шаблонов
if (!isInTemplatesDir(document.uri.fsPath, templatesDir)) { if (!isInTemplatesDir(document.uri.fsPath, templatesDir)) {
return; return;

View File

@@ -120,16 +120,16 @@ export async function showConfigWebview(context: vscode.ExtensionContext) {
} }
panel.webview.onDidReceiveMessage( panel.webview.onDidReceiveMessage(
msg => { async msg => {
if (msg.type === 'save') { if (msg.type === 'save') {
writeConfig(msg.data); await writeConfig(msg.data);
vscode.window.showInformationMessage('Настройки сохранены!'); vscode.window.showInformationMessage('Настройки сохранены!');
panel.dispose(); panel.dispose();
} }
if (msg.type === 'setLanguage') { if (msg.type === 'setLanguage') {
// Сохраняем язык в конфиг и перерисовываем webview // Сохраняем язык в конфиг и перерисовываем webview
config.language = msg.language; config.language = msg.language;
writeConfig(config); await writeConfig(config);
setHtml(msg.language === 'en' ? 'en' : 'ru'); setHtml(msg.language === 'en' ? 'en' : 'ru');
} }
}, },

View File

@@ -156,7 +156,7 @@ export async function showTemplateAndVarsWebview(
if (message.language) language = message.language; if (message.language) language = message.language;
// Сохраняем язык в конфиг // Сохраняем язык в конфиг
const oldConfig = readConfig(); const oldConfig = readConfig();
writeConfig({ ...oldConfig, language }); await writeConfig({ ...oldConfig, language });
currentTemplate = message.template || templates[0] || ''; currentTemplate = message.template || templates[0] || '';
// Получаем переменные для выбранного шаблона // Получаем переменные для выбранного шаблона
let baseVars: string[] = []; let baseVars: string[] = [];