Asper Header  1.0.14
The header injector extension
Loading...
Searching...
No Matches
randomLogo.ts
Go to the documentation of this file.
1
83import * as fs from 'fs/promises';
84import * as path from 'path';
85import * as vscode from 'vscode';
86import { logger } from "./logger";
87import { getMessage } from "./messageProvider";
88import { LazyFileLoader } from "./lazyFileLoad";
89
98export interface logo {
100 logoContent: string[],
102 fileName: string
103}
104
132export class RandomLogo {
134 private cwd: string | undefined = undefined;
136 private rootDir: string | undefined = undefined;
138 private liveLogoFiles: LazyFileLoader[] = [];
139
150 constructor(rootDir: string | undefined = undefined, cwd: string | undefined = undefined) {
151 logger.debug(getMessage("inFunction", "constructor", "RandomLogo"));
152 if (rootDir) {
153 this.rootDir = rootDir;
154 this.gatherAllLogoFiles(this.rootDir);
155 }
156 if (cwd) {
157 this.cwd = cwd;
158 }
159 }
160
180 async updateRootDir(basePath: string, alternateBasePath: string | undefined = undefined): Promise<boolean> {
181 logger.debug(getMessage("inFunction", "updateRootDir", "RandomLogo"));
182 this.rootDir = basePath;
183 try {
184 await this.gatherAllLogoFiles(this.rootDir);
185 logger.debug(getMessage("foundLogoRootDir", basePath));
186 return true;
187 } catch (e) {
188 logger.error(getMessage("logoRootDirUpdateError", String(e)));
189 if (alternateBasePath === undefined) {
190 logger.warning(getMessage("alternateLogoDirectoryNotProvided"));
191 return false;
192 }
193 this.rootDir = alternateBasePath;
194 try {
195 await this.gatherAllLogoFiles(this.rootDir);
196 logger.debug(getMessage("foundAlternateLogoRootDir", alternateBasePath));
197 return true;
198 } catch (e) {
199 logger.error(getMessage("alternateLogoDirectoryNotFound", alternateBasePath, String(e)));
200 return false;
201 }
202 }
203 }
204
214 updateCurrentWorkingDirectory(cwd: string): boolean {
215 logger.debug(getMessage("inFunction", "updateCurrentWorkingDirectory", "RandomLogo"));
216 this.cwd = cwd;
217 return true;
218 }
219
229 private getRandomNumber(maxValue: number): number {
230 logger.debug(getMessage("inFunction", "getRandomNumber", "RandomLogo"));
231 return Math.floor(Math.random() * maxValue);
232 }
233
260 private async gatherAllLogoFiles(rootDir: string | undefined = undefined): Promise<void> {
261 logger.debug(getMessage("inFunction", "gatherAllLogoFiles", "RandomLogo"));
262 if (!rootDir && !this.rootDir) {
263 throw Error(getMessage("logoNoRootDir"));
264 }
265 if (!rootDir && this.rootDir) {
266 rootDir = this.rootDir;
267 }
268 if (rootDir) {
269 const dirents = await fs.readdir(rootDir, { withFileTypes: true });
270
271 for (const dirent of dirents) {
272 const resolvedPath = path.resolve(rootDir, dirent.name);
273 if (dirent.isDirectory()) {
274 await this.gatherAllLogoFiles(resolvedPath);
275 } else if (resolvedPath.endsWith(".txt")) {
276 this.liveLogoFiles.push(new LazyFileLoader(resolvedPath, this.cwd));
277 } else {
278 logger.info(getMessage("logoMessage", resolvedPath));
279 }
280 }
281 }
282 }
302 private copyButtonScript(): string {
303 logger.debug(getMessage("inFunction", "copyButtonScript", "RandomLogo"));
304 return `
305<script>
306 const vscode = acquireVsCodeApi();
307 console.log(\`vscode = \${vscode}\`);
308 document.getElementById('copyBtn').addEventListener('click', () => {
309 const content = document.getElementById('ascii').innerText;
310 navigator.clipboard.writeText(content).then(() => {
311 vscode.postMessage({ type: 'copied' });
312 });
313 });
314</script>
315 `;
316 }
317
338 private zoomScript(): string {
339 logger.debug(getMessage("inFunction", "zoomScript", "RandomLogo"));
340 return `
341<script>
342 let currentSize = 20;
343 function updateFontSize(sizeDifference) {
344 console.log(\`sizeDifference = \${sizeDifference}\`);
345 const asciiPre = document.getElementById('ascii');
346 console.log(\`asciiPre = \${JSON.stringify(asciiPre)}\`);
347 console.log(\`currentSize = \${currentSize}\`);
348 if (currentSize + sizeDifference >= 2) {
349 currentSize += sizeDifference;
350 console.log(\`currentSize (after update) = \${currentSize}\`);
351 } else {
352 console.log(\`currentSize (no update) = \${currentSize}\`);
353 }
354 asciiPre.style.fontSize = currentSize + "px";
355 asciiPre.style.lineHeight = currentSize + "px";
356 console.log(\`newSize = \${asciiPre.style.fontSize}\`);
357 }
358
359 document.getElementById('zoomInBtn').addEventListener('click', () => {
360 updateFontSize((2));
361 });
362
363 document.getElementById('zoomOutBtn').addEventListener('click', () => {
364 updateFontSize((-2));
365 });
366
367 // init
368 updateFontSize();
369</script>
370 `;
371 }
372
388 private pageStyle(): string {
389 logger.debug(getMessage("inFunction", "pageStyle", "RandomLogo"));
390 return `
391 <style>
392 body { font-family: sans-serif; padding: 20px; }
393 h1 { font-size: 20px; margin-bottom: 0.2em; }
394 h2 { margin-top: 1.2em; }
395 pre { font-size: 10px; line-height: 10px; white-space: pre; }
396 button { margin: 10px 0; padding: 5px 12px; font-size: 14px; }
397 </style>
398 `;
399 }
400
428 async getRandomLogoFromFolder(): Promise<logo> {
429 logger.debug(getMessage("inFunction", "getRandomLogoFromFolder", "RandomLogo"));
430 if (this.liveLogoFiles.length === 0) {
431 await this.gatherAllLogoFiles();
432 }
433
434 if (this.liveLogoFiles.length === 0) {
435 const errMsg = getMessage("watermarkJsonFileInvalid");
436 logger.Gui.error(errMsg);
437 throw new Error(errMsg);
438 }
439
440 const chosenIndex = this.getRandomNumber(this.liveLogoFiles.length);
441 const chosenFile = this.liveLogoFiles[chosenIndex];
442 const content = await chosenFile.get();
443
444 // Assuming logos are stored as array of lines, otherwise fallback to single string
445 const lines = content.split(/\r?\n/);
446
447 return {
448 fileName: path.basename(chosenFile.getFilePath() || ""),
449 logoContent: lines
450 };
451 }
452
453
486 async displayRandomLogoInWindow() {
487 logger.debug(getMessage("inFunction", "displayRandomLogoInWindow", "RandomLogo"));
488 const randomLogo: logo = await this.getRandomLogoFromFolder();
489
490 const panel = vscode.window.createWebviewPanel(
491 getMessage("logoView"),
492 randomLogo.fileName,
493 vscode.ViewColumn.One,
494 { enableScripts: true }
495 );
496
497 const watermark = randomLogo.logoContent;
498 logger.info(getMessage("logoChosen", watermark));
499 let asciiArt = "";
500 if (typeof watermark === "string") {
501 asciiArt = watermark;
502 } else if (Array.isArray(watermark)) {
503 asciiArt = watermark.join("\n");
504 } else if (watermark === undefined) {
505 asciiArt = getMessage("logoNotFound");
506 }
507
508 const copyButton: string = this.copyButtonScript();
509 const pageStyle: string = this.pageStyle();
510 const zoomScript: string = this.zoomScript();
511
512 panel.webview.html = `
513<!DOCTYPE html>
514<html lang="en">
515<head>
516 <meta charset="UTF-8">
517 ${pageStyle}
518</head>
519<body>
520 <div>
521 <button id="copyBtn">${getMessage('logoCopyAscii')}</button>
522 <button id="zoomInBtn">${getMessage('logoZoomIn')}</button>
523 <button id="zoomOutBtn">${getMessage('logoZoomOut')}</button>
524 </div>
525 <h1>${getMessage('logoName')}: ${randomLogo.fileName}</h1>
526 <pre id="ascii">${asciiArt}</pre>
527 ${copyButton}
528 ${zoomScript}
529</body>
530</html>
531`;
532
533 panel.webview.onDidReceiveMessage(message => {
534 if (message.type === "copied") {
535 logger.Gui.info(getMessage("logoCopied", randomLogo.fileName));
536 }
537 });
538
539 logger.Gui.info(getMessage("logoDisplayed", randomLogo.fileName));
540 }
541}
Generic lazy file loader with caching and type safety @template T The expected type of the loaded fil...
export const randomLogo
Whether to use random logo selection instead of default logo.
Definition constants.ts:235
import fs from fs
Definition esbuild.js:9
Structure representing a loaded ASCII art logo with metadata.
Structure representing a loaded ASCII art watermark with font metadata.
import type
export const logger
Singleton logger instance providing unified logging interface for the entire extension.
Definition logger.ts:910
export const getMessage
Exported function for direct message retrieval.
export const Record< string,(...args:any[])=> string
import *as vscode from vscode
Definition randomLogo.ts:85
import *as path from path
Definition randomLogo.ts:84