151 lines
4.9 KiB
TypeScript
151 lines
4.9 KiB
TypeScript
import * as plugins from './plugins.js';
|
|
import * as paths from '../paths.js';
|
|
import * as interfaces from '../interfaces/index.js';
|
|
|
|
export class Base64TsOutput {
|
|
private files: interfaces.IBase64File[] = [];
|
|
private cwd: string;
|
|
|
|
constructor(cwd: string = paths.cwd) {
|
|
this.cwd = cwd;
|
|
}
|
|
|
|
/**
|
|
* Add a file with its content to the output
|
|
*/
|
|
public addFile(filePath: string, content: Buffer | string): void {
|
|
const contentBuffer = typeof content === 'string' ? Buffer.from(content, 'utf-8') : content;
|
|
const contentBase64 = contentBuffer.toString('base64');
|
|
this.files.push({
|
|
path: filePath,
|
|
contentBase64,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Add files matching a glob pattern
|
|
*/
|
|
public async addFilesFromGlob(pattern: string): Promise<void> {
|
|
const absolutePattern = plugins.smartpath.transform.toAbsolute(pattern, this.cwd) as string;
|
|
const patternDir = plugins.path.dirname(absolutePattern);
|
|
const patternBase = plugins.path.basename(absolutePattern);
|
|
|
|
// Check if it's a directory pattern or file pattern
|
|
const isGlobPattern = patternBase.includes('*');
|
|
|
|
if (isGlobPattern) {
|
|
// Handle glob patterns
|
|
const dirPath = patternDir.replace(/\/\*\*$/, '');
|
|
const dirExists = await plugins.fs.directory(dirPath).exists();
|
|
if (!dirExists) {
|
|
console.log(`Directory does not exist: ${dirPath}`);
|
|
return;
|
|
}
|
|
|
|
const isRecursive = pattern.includes('**');
|
|
let entries;
|
|
if (isRecursive) {
|
|
entries = await plugins.fs.directory(dirPath).recursive().list();
|
|
} else {
|
|
entries = await plugins.fs.directory(dirPath).list();
|
|
}
|
|
|
|
// Filter by pattern if needed
|
|
const filePattern = patternBase.replace('*', '.*');
|
|
const regex = new RegExp(filePattern);
|
|
|
|
for (const entry of entries) {
|
|
if (!entry.isDirectory && regex.test(entry.name)) {
|
|
// entry.path may be absolute or relative - handle both cases
|
|
const fullPath = plugins.path.isAbsolute(entry.path)
|
|
? entry.path
|
|
: plugins.path.join(dirPath, entry.path);
|
|
// Use path relative to pattern's base dir (not cwd) for web serving
|
|
const relativePath = plugins.path.relative(dirPath, fullPath);
|
|
const content = await plugins.fs.file(fullPath).read();
|
|
this.addFile(relativePath, content);
|
|
}
|
|
}
|
|
} else {
|
|
// Handle single file path
|
|
const fileExists = await plugins.fs.file(absolutePattern).exists();
|
|
if (!fileExists) {
|
|
console.log(`File does not exist: ${absolutePattern}`);
|
|
return;
|
|
}
|
|
const relativePath = plugins.path.relative(this.cwd, absolutePattern);
|
|
const content = await plugins.fs.file(absolutePattern).read();
|
|
this.addFile(relativePath, content);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generate TypeScript file content
|
|
* @param maxLineLength - Max chars per line for base64 strings. 0 or undefined = unlimited (default)
|
|
*/
|
|
public generateTypeScript(maxLineLength?: number): string {
|
|
// Default behavior: no line splitting (unlimited)
|
|
if (!maxLineLength || maxLineLength <= 0) {
|
|
const filesJson = JSON.stringify(this.files, null, 2);
|
|
return `// Auto-generated by tsbundle - do not edit
|
|
export const files: { path: string; contentBase64: string }[] = ${filesJson};
|
|
`;
|
|
}
|
|
|
|
// Split base64 strings into chunks when maxLineLength is specified
|
|
const formatBase64 = (base64: string): string => {
|
|
if (base64.length <= maxLineLength) {
|
|
return `"${base64}"`;
|
|
}
|
|
|
|
const chunks: string[] = [];
|
|
for (let i = 0; i < base64.length; i += maxLineLength) {
|
|
chunks.push(base64.slice(i, i + maxLineLength));
|
|
}
|
|
|
|
return `"" +\n "${chunks.join('" +\n "')}"`;
|
|
};
|
|
|
|
const filesFormatted = this.files.map(file => {
|
|
return ` {
|
|
"path": "${file.path}",
|
|
"contentBase64": ${formatBase64(file.contentBase64)}
|
|
}`;
|
|
}).join(',\n');
|
|
|
|
return `// Auto-generated by tsbundle - do not edit
|
|
export const files: { path: string; contentBase64: string }[] = [
|
|
${filesFormatted}
|
|
];
|
|
`;
|
|
}
|
|
|
|
/**
|
|
* Write the TypeScript file to disk
|
|
* @param outputPath - Output file path
|
|
* @param maxLineLength - Max chars per line for base64 strings. 0 or undefined = unlimited (default)
|
|
*/
|
|
public async writeToFile(outputPath: string, maxLineLength?: number): Promise<void> {
|
|
const absolutePath = plugins.smartpath.transform.toAbsolute(outputPath, this.cwd) as string;
|
|
const outputDir = plugins.path.dirname(absolutePath);
|
|
await plugins.fs.directory(outputDir).create();
|
|
const content = this.generateTypeScript(maxLineLength);
|
|
await plugins.fs.file(absolutePath).encoding('utf8').write(content);
|
|
console.log(`Generated base64ts output: ${outputPath}`);
|
|
}
|
|
|
|
/**
|
|
* Get all collected files
|
|
*/
|
|
public getFiles(): interfaces.IBase64File[] {
|
|
return this.files;
|
|
}
|
|
|
|
/**
|
|
* Clear all collected files
|
|
*/
|
|
public clear(): void {
|
|
this.files = [];
|
|
}
|
|
}
|