✨feature: First build
This commit is contained in:
@@ -1 +1 @@
|
||||
/* {{ BLOCK_NAME }} block styles */
|
||||
/* {{BLOCK_NAME}} block styles */
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
<?php
|
||||
/**
|
||||
* Block Name: {{ BLOCK_NAME }}
|
||||
* Block Name: {{BLOCK_NAME}}
|
||||
*
|
||||
* Add a description of your block. Shows up in the block inserter
|
||||
* Add a description of your block. Shows up in the block inserter.
|
||||
*
|
||||
* @package BasicWP
|
||||
*/
|
||||
|
||||
namespace BasicWP;
|
||||
|
||||
$classes = '{{ BLOCK_SLUG }}';
|
||||
$classes = '{{BLOCK_SLUG}}';
|
||||
|
||||
/**
|
||||
* NOTE: DO NOT remove this function call - it is required to avoid editor issues.
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
{
|
||||
"name": "acf/{{ BLOCK_SLUG }}",
|
||||
"title": "{{ BLOCK_NAME }}",
|
||||
"description": "",
|
||||
"name": "acf/{{BLOCK_SLUG}}",
|
||||
"title": "{{BLOCK_NAME}}",
|
||||
"description": "Add a description of your block. Shows up in the block inserter.",
|
||||
"style": [
|
||||
"file:./{{ BLOCK_SLUG }}.css"
|
||||
"file:./{{BLOCK_SLUG}}.css"
|
||||
],
|
||||
"category": "vdi-block",
|
||||
"icon": "block-default",
|
||||
"keywords": [
|
||||
"{{ BLOCK_NAME }}"
|
||||
"{{BLOCK_NAME}}"
|
||||
],
|
||||
"acf": {
|
||||
"blockVersion": 3,
|
||||
"autoInlineEditing": true,
|
||||
"mode": "preview",
|
||||
"renderTemplate": "{{ BLOCK_SLUG }}.php"
|
||||
"renderTemplate": "{{BLOCK_SLUG}}.php"
|
||||
},
|
||||
"supports": {
|
||||
"align": true,
|
||||
|
||||
53
package.json
Normal file
53
package.json
Normal file
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"name": "vdi-acf-block-scaffold",
|
||||
"displayName": "VDI ACF Block Scaffold",
|
||||
"description": "Scaffold WordPress ACF blocks from a template.",
|
||||
"version": "0.0.1",
|
||||
"publisher": "vdi",
|
||||
"engines": {
|
||||
"vscode": "^1.80.0"
|
||||
},
|
||||
"categories": [
|
||||
"Other"
|
||||
],
|
||||
"activationEvents": [
|
||||
"onCommand:vdi-acf-block-scaffold.createBlock"
|
||||
],
|
||||
"main": "./out/extension.js",
|
||||
"contributes": {
|
||||
"commands": [
|
||||
{
|
||||
"command": "vdi-acf-block-scaffold.createBlock",
|
||||
"title": "VDI: Create ACF Block"
|
||||
}
|
||||
],
|
||||
"configuration": {
|
||||
"title": "VDI ACF Block Scaffold",
|
||||
"properties": {
|
||||
"vdiAcfBlockScaffold.parentDirectory": {
|
||||
"type": "string",
|
||||
"default": "views/blocks",
|
||||
"description": "Workspace-relative parent directory where new blocks are created."
|
||||
}
|
||||
}
|
||||
},
|
||||
"keybindings": [
|
||||
{
|
||||
"command": "vdi-acf-block-scaffold.createBlock",
|
||||
"key": "ctrl+alt+b",
|
||||
"mac": "cmd+alt+b",
|
||||
"when": "editorTextFocus"
|
||||
}
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"vscode:prepublish": "npm run compile",
|
||||
"compile": "tsc -p ./",
|
||||
"watch": "tsc -watch -p ./"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.30",
|
||||
"@types/vscode": "^1.80.0",
|
||||
"typescript": "^5.4.0"
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
19
tsconfig.json
Normal file
19
tsconfig.json
Normal file
@@ -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"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user