Skip to content

Commit

Permalink
feat: 🎸 user facing command Blade: Format Document
Browse files Browse the repository at this point in the history
✅ Closes: #60
  • Loading branch information
shufo committed Jun 22, 2022
1 parent 1914cab commit 176267a
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 1 deletion.
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@
"icon": "icon.png",
"main": "./dist/extension.js",
"contributes": {
"commands": [
{
"command": "vscode-blade-formatter.format",
"title": "Blade: Format Document"
}
],
"jsonValidation": [
{
"fileMatch": ".bladeformatterrc.json",
Expand Down
40 changes: 40 additions & 0 deletions src/commands.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import vscode, { commands, TextEditor, TextEditorEdit, window, WorkspaceConfiguration } from "vscode";
import { readRuntimeConfig } from './runtimeConfig';
import { getCoreNodeModule } from "./util";
import { Formatter } from "blade-formatter";
import { Logger } from "./logger";

const vsctmModule = getCoreNodeModule("vscode-textmate");
const onigurumaModule = getCoreNodeModule("vscode-oniguruma");
const { Range, Position } = vscode;

export const formatFromCommand =
async function (editor: TextEditor, edit: TextEditorEdit) {
try {
const extConfig = vscode.workspace.getConfiguration(
"bladeFormatter.format"
);
const runtimeConfig = readRuntimeConfig(editor.document.uri.fsPath);
const options = {
vsctm: vsctmModule,
oniguruma: onigurumaModule,
indentSize: extConfig.indentSize,
wrapLineLength: extConfig.wrapLineLength,
wrapAttributes: extConfig.wrapAttributes,
useTabs: extConfig.useTabs,
sortTailwindcssClasses: extConfig.sortTailwindcssClasses,
...runtimeConfig,
};
const originalText = editor.document.getText();
const lastLine = editor.document.lineAt(editor.document.lineCount - 1);
const range = new Range(new Position(0, 0), lastLine.range.end);
const formatted = await new Formatter(options).formatContent(originalText);

await editor.edit((editBuilder) => {
editBuilder.replace(range, formatted);
});
} catch (e) {
const logger = new Logger();
logger.logError("Error formatting document", e);
}
}
1 change: 1 addition & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ export const enum ExtensionConstants {
firstActivationStorageKey = 'firstActivation',
globalVersionKey = 'vscode-blade-formatter-version',
displayName = 'Laravel Blade Formatter',
formatCommandKey = 'vscode-blade-formatter.format',
}
8 changes: 7 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import vscode, { WorkspaceConfiguration } from "vscode";
import vscode, { commands, window, WorkspaceConfiguration } from "vscode";
import { ExtensionContext } from "vscode";
import path from "path";
import findConfig from "find-config";
Expand All @@ -10,6 +10,7 @@ import { telemetry, TelemetryEventNames } from './telemetry';
import { readRuntimeConfig } from './runtimeConfig';
import { ExtensionConstants } from "./constants";
import { messages } from "./messages";
import { formatFromCommand } from "./commands";
import { getCoreNodeModule } from "./util";

const { Range, Position } = vscode;
Expand Down Expand Up @@ -41,6 +42,11 @@ export function activate(context: ExtensionContext) {
context.globalState.update(ExtensionConstants.firstActivationStorageKey, false);
}

commands.registerTextEditorCommand(
ExtensionConstants.formatCommandKey,
formatFromCommand
);

context.subscriptions.push(
vscode.languages.registerDocumentFormattingEditProvider("blade", {
provideDocumentFormattingEdits(document: vscode.TextDocument, vscodeOpts: vscode.FormattingOptions): any {
Expand Down
108 changes: 108 additions & 0 deletions src/logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { window } from "vscode";

type LogLevel = "DEBUG" | "INFO" | "WARN" | "ERROR" | "NONE";

export class Logger {
private outputChannel = window.createOutputChannel("BladeFormatter");

private logLevel: LogLevel = "INFO";

public setOutputLevel(logLevel: LogLevel) {
this.logLevel = logLevel;
}

/**
* Append messages to the output channel and format it with a title
*
* @param message The message to append to the output channel
*/
public logDebug(message: string, data?: unknown): void {
if (
this.logLevel === "NONE" ||
this.logLevel === "INFO" ||
this.logLevel === "WARN" ||
this.logLevel === "ERROR"
) {
return;
}
this.logMessage(message, "DEBUG");
if (data) {
this.logObject(data);
}
}

/**
* Append messages to the output channel and format it with a title
*
* @param message The message to append to the output channel
*/
public logInfo(message: string, data?: unknown): void {
if (
this.logLevel === "NONE" ||
this.logLevel === "WARN" ||
this.logLevel === "ERROR"
) {
return;
}
this.logMessage(message, "INFO");
if (data) {
this.logObject(data);
}
}

/**
* Append messages to the output channel and format it with a title
*
* @param message The message to append to the output channel
*/
public logWarning(message: string, data?: unknown): void {
if (this.logLevel === "NONE" || this.logLevel === "ERROR") {
return;
}
this.logMessage(message, "WARN");
if (data) {
this.logObject(data);
}
}

public logError(message: string, error?: unknown) {
if (this.logLevel === "NONE") {
return;
}
this.logMessage(message, "ERROR");
if (typeof error === "string") {
// Errors as a string usually only happen with
// plugins that don't return the expected error.
this.outputChannel.appendLine(error);
} else if (error instanceof Error) {
if (error?.message) {
this.logMessage(error.message, "ERROR");
}
if (error?.stack) {
this.outputChannel.appendLine(error.stack);
}
} else if (error) {
this.logObject(error);
}
}

public show() {
this.outputChannel.show();
}

private logObject(data: unknown): void {
const message = JSON.stringify(data, null, 2); // dont use prettier to keep it simple

this.outputChannel.appendLine(message);
}

/**
* Append messages to the output channel and format it with a title
*
* @param message The message to append to the output channel
*/
private logMessage(message: string, logLevel: LogLevel): void {
const title = new Date().toLocaleTimeString();
this.outputChannel.appendLine(`["${logLevel}" - ${title}] ${message}`);
}
}

0 comments on commit 176267a

Please sign in to comment.