✨feature: First build
This commit is contained in:
156
src/extension.ts
Normal file
156
src/extension.ts
Normal file
@@ -0,0 +1,156 @@
|
||||
import * as path from "path";
|
||||
import { promises as fs } from "fs";
|
||||
import * as vscode from "vscode";
|
||||
|
||||
const OUTPUT_CHANNEL = vscode.window.createOutputChannel("VDI ACF Block Scaffold");
|
||||
|
||||
export function activate(context: vscode.ExtensionContext): void {
|
||||
const command = vscode.commands.registerCommand(
|
||||
"vdi-acf-block-scaffold.createBlock",
|
||||
async () => {
|
||||
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<string>(
|
||||
"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<void> {
|
||||
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<boolean> {
|
||||
try {
|
||||
await fs.access(targetPath);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user