angular/adev/shared-docs/pipeline/examples/zip/builder.mts
Joey Perrott 5f1c08d75f build: migrate adev shared-docs package to use ts_project (#61193)
Migrate the build rules for shared docs to use ts_project

PR Close #61193
2025-05-09 16:30:05 +00:00

112 lines
3.2 KiB
TypeScript

/*!
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import {join} from 'path';
import {readFile} from 'fs/promises';
import {copyFolder, createFolder} from '../shared/file-system.mjs';
import {glob} from 'tinyglobby';
import {regionParser} from '../../guides/extensions/docs-code/regions/region-parser.mjs';
import {appendCopyrightToFile} from '../shared/copyright.mjs';
import {FileType} from '../../guides/extensions/docs-code/sanitizers/eslint.mjs';
import {EXCLUDE_FILES, CONFIG_FILENAME} from './defaults.mjs';
import {zip, strToU8} from 'fflate';
import {FileAndContent} from '../../../interfaces';
interface ZipConfig {
ignore: string[];
files: string[];
}
export async function generateZipExample(
exampleDir: string,
workingDir: string,
templateDir: string,
) {
const config = await readFile(join(exampleDir, CONFIG_FILENAME), 'utf-8');
const stackblitzConfig: ZipConfig = JSON.parse(config) as ZipConfig;
await createFolder(workingDir);
// Copy template files to TEMP folder
await copyFolder(templateDir, workingDir);
// Copy example files to TEMP folder
await copyFolder(exampleDir, workingDir);
const includedPaths = await getIncludedPaths(workingDir, stackblitzConfig);
const filesObj: Record<string, Uint8Array> = {};
for (const path of includedPaths) {
const file = await getFileAndContent(workingDir, path);
filesObj[file.path] = typeof file.content === 'string' ? strToU8(file.content) : file.content;
}
return new Promise<Uint8Array>((resolve, reject) => {
zip(filesObj, (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
}
async function getIncludedPaths(workingDir: string, config: ZipConfig): Promise<string[]> {
const defaultIncludes = [
'**/*.ts',
'**/*.js',
'**/*.css',
'**/*.html',
'**/*.md',
'**/*.json',
'**/*.svg',
];
return glob(defaultIncludes, {
cwd: workingDir,
onlyFiles: true,
dot: true,
ignore: config.ignore,
});
}
async function getFileAndContent(workingDir: string, path: string): Promise<FileAndContent> {
let content = await readFile(join(workingDir, path), 'utf-8');
content = appendCopyrightToFile(path, content);
content = extractRegions(path, content);
return {content, path};
}
async function createPostData(
exampleDir: string,
config: ZipConfig,
exampleFilePaths: string[],
): Promise<Record<string, string>> {
const postData: Record<string, string> = {};
for (const filePath of exampleFilePaths) {
if (EXCLUDE_FILES.some((excludedFile) => filePath.endsWith(excludedFile))) {
continue;
}
let content = await readFile(join(exampleDir, filePath), 'utf-8');
content = appendCopyrightToFile(filePath, content);
content = extractRegions(filePath, content);
postData[`project[files][${filePath}]`] = content;
}
return postData;
}
function extractRegions(path: string, contents: string): string {
const fileType: FileType | undefined = path?.split('.').pop() as FileType;
const regionParserResult = regionParser(contents, fileType);
return regionParserResult.contents;
}