diff --git a/block-template/block-template.css b/block-template/block-template.css index b231c2d..2be10c7 100644 --- a/block-template/block-template.css +++ b/block-template/block-template.css @@ -1 +1 @@ -/* {{ BLOCK_NAME }} block styles */ +/* {{BLOCK_NAME}} block styles */ diff --git a/block-template/block-template.php b/block-template/block-template.php index d453fc5..c2d8741 100644 --- a/block-template/block-template.php +++ b/block-template/block-template.php @@ -1,15 +1,15 @@ { + try { + const workspaceFolder = vscode.workspace.workspaceFolders?.[0]; + if (!workspaceFolder) { + vscode.window.showErrorMessage("Open a workspace folder first."); + return; + } + + const blockNameInput = await vscode.window.showInputBox({ + prompt: "Enter the new block name", + placeHolder: "Testimonial", + validateInput: (value) => { + if (!value || !value.trim()) { + return "Block name is required."; + } + return null; + } + }); + + if (!blockNameInput) { + return; + } + + const blockName = blockNameInput.trim(); + const blockSlug = toSlug(blockName); + if (!blockSlug) { + vscode.window.showErrorMessage( + "Block name must include at least one letter or number." + ); + return; + } + + const config = vscode.workspace.getConfiguration("vdiAcfBlockScaffold"); + const parentSetting = config.get( + "parentDirectory", + "views/blocks" + ); + const parentDir = path.isAbsolute(parentSetting) + ? parentSetting + : path.join(workspaceFolder.uri.fsPath, parentSetting); + const targetDir = path.join(parentDir, blockSlug); + + if (await pathExists(targetDir)) { + vscode.window.showErrorMessage( + `A block named "${blockSlug}" already exists.` + ); + return; + } + + const templateDir = path.join(context.extensionPath, "block-template"); + if (!(await pathExists(templateDir))) { + vscode.window.showErrorMessage( + "Block template folder is missing from the extension." + ); + return; + } + + await fs.mkdir(targetDir, { recursive: true }); + + const templateEntries = await fs.readdir(templateDir, { + withFileTypes: true + }); + + for (const entry of templateEntries) { + if (!entry.isFile()) { + continue; + } + + const sourcePath = path.join(templateDir, entry.name); + const content = await fs.readFile(sourcePath, "utf8"); + const replaced = content + .replace(/{{BLOCK_NAME}}/g, blockName) + .replace(/{{BLOCK_SLUG}}/g, blockSlug); + + const destinationName = mapTemplateFileName(entry.name, blockSlug); + const destinationPath = path.join(targetDir, destinationName); + + if (await pathExists(destinationPath)) { + vscode.window.showErrorMessage( + `File already exists: ${destinationName}` + ); + return; + } + + await fs.writeFile(destinationPath, replaced, "utf8"); + } + + await openCreatedFiles(targetDir, blockSlug); + vscode.window.showInformationMessage( + `Created ACF block: ${blockName}` + ); + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + OUTPUT_CHANNEL.appendLine(message); + vscode.window.showErrorMessage( + "Failed to create ACF block. See output for details." + ); + } + } + ); + + context.subscriptions.push(command, OUTPUT_CHANNEL); +} + +export function deactivate(): void { + OUTPUT_CHANNEL.dispose(); +} + +function toSlug(value: string): string { + return value + .toLowerCase() + .trim() + .replace(/[^a-z0-9]+/g, "-") + .replace(/^-+|-+$/g, ""); +} + +function mapTemplateFileName(filename: string, slug: string): string { + if (filename === "block-template.php") { + return `${slug}.php`; + } + if (filename === "block-template.css") { + return `${slug}.css`; + } + return filename; +} + +async function openCreatedFiles(dir: string, slug: string): Promise { + const filesToOpen = ["block.json", `${slug}.php`, `${slug}.css`]; + + for (const filename of filesToOpen) { + const filePath = path.join(dir, filename); + if (!(await pathExists(filePath))) { + continue; + } + const doc = await vscode.workspace.openTextDocument(filePath); + await vscode.window.showTextDocument(doc, { preview: false }); + } +} + +async function pathExists(targetPath: string): Promise { + try { + await fs.access(targetPath); + return true; + } catch { + return false; + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..9930618 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "CommonJS", + "lib": [ + "ES2020" + ], + "rootDir": "src", + "outDir": "out", + "sourceMap": true, + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true + }, + "exclude": [ + "node_modules", + ".vscode-test" + ] +}