105 lines
3.4 KiB
TypeScript
105 lines
3.4 KiB
TypeScript
import * as fs from 'fs';
|
|
import * as path from 'path';
|
|
import { BaseProcessor, ProcessorContext, ProcessorResult } from './base-processor';
|
|
import { TemplateTransformer } from './template/template-transformer';
|
|
|
|
export class TemplateProcessor extends BaseProcessor {
|
|
private transformer = new TemplateTransformer();
|
|
|
|
get name(): string {
|
|
return 'template-processor';
|
|
}
|
|
|
|
async process(context: ProcessorContext): Promise<ProcessorResult> {
|
|
if (!context.source.includes('template')) {
|
|
return this.noChange(context.source);
|
|
}
|
|
|
|
let source = context.source;
|
|
let modified = false;
|
|
|
|
source = await this.processTemplateUrls(source, context);
|
|
if (source !== context.source) modified = true;
|
|
|
|
const inlineResult = this.processInlineTemplates(source);
|
|
if (inlineResult.modified) {
|
|
source = inlineResult.source;
|
|
modified = true;
|
|
}
|
|
|
|
return modified ? this.changed(source) : this.noChange(source);
|
|
}
|
|
|
|
private async processTemplateUrls(source: string, context: ProcessorContext): Promise<string> {
|
|
const patterns = [
|
|
/templateUrl\s*[=:]\s*['"`]([^'"`]+)['"`]/g,
|
|
];
|
|
|
|
let result = source;
|
|
|
|
for (const pattern of patterns) {
|
|
const matches = [...source.matchAll(pattern)];
|
|
|
|
for (const match of matches.reverse()) {
|
|
const templatePath = match[1];
|
|
const fullPath = path.resolve(context.fileDir, templatePath);
|
|
|
|
if (!fs.existsSync(fullPath)) {
|
|
throw new Error(`Template not found: ${fullPath}`);
|
|
}
|
|
|
|
let content = await fs.promises.readFile(fullPath, 'utf8');
|
|
content = this.transformer.transformAll(content);
|
|
content = this.escapeTemplate(content);
|
|
|
|
result = result.replace(match[0], `template: \`${content}\``);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private processInlineTemplates(source: string): { source: string; modified: boolean } {
|
|
const patterns = [
|
|
{ regex: /template\s*:\s*`([^`]*)`/g, quote: '`' },
|
|
{ regex: /template\s*:\s*'([^']*)'/g, quote: "'" },
|
|
{ regex: /template\s*:\s*"([^"]*)"/g, quote: '"' },
|
|
];
|
|
|
|
let result = source;
|
|
let modified = false;
|
|
|
|
for (const { regex } of patterns) {
|
|
const matches = [...result.matchAll(regex)];
|
|
|
|
for (const match of matches.reverse()) {
|
|
let content = this.unescapeTemplate(match[1]);
|
|
content = this.transformer.transformAll(content);
|
|
content = this.escapeTemplate(content);
|
|
|
|
const newTemplate = `template: \`${content}\``;
|
|
if (match[0] !== newTemplate) {
|
|
result = result.slice(0, match.index!) + newTemplate + result.slice(match.index! + match[0].length);
|
|
modified = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return { source: result, modified };
|
|
}
|
|
|
|
private escapeTemplate(content: string): string {
|
|
return content
|
|
.replace(/\\/g, '\\\\')
|
|
.replace(/`/g, '\\`')
|
|
.replace(/\$/g, '\\$');
|
|
}
|
|
|
|
private unescapeTemplate(content: string): string {
|
|
return content
|
|
.replace(/\\`/g, '`')
|
|
.replace(/\\\$/g, '$')
|
|
.replace(/\\\\/g, '\\');
|
|
}
|
|
}
|