import { SDTFEngine, SpecifyDesignTokenFormat, TreePath, createSDTFEngine, } from '@specifyapp/specify-design-token-format'; import { DeriveBuiltInParserHandlerFromDefinition } from '../../internals/createBuiltInParserDefinition.js'; import type { ToBitmapFileParserDefinition } from './definition.js'; import { SpecifyError, specifyErrors } from '../../../errors/index.js'; import { FilesOutput } from '../../../parsersEngine/index.js'; import { DEFAULT_FILENAME_TEMPLATE_WITH_MODES, DEFAULT_FILENAME_TEMPLATE_WITHOUT_MODES, makeFilename, } from '../../utils/filenameTemplateVariables.js'; import { generateBitmapDataBoxAssets } from '../../shared/to-bitmap-file/generatesBitmapDataBoxFiles.js'; export const toBitmapFileHandler: DeriveBuiltInParserHandlerFromDefinition< ToBitmapFileParserDefinition > = async (previous, toolbox, parserOptions, outputOptions, _context) => { let tokenTree: SpecifyDesignTokenFormat; let sdtfEngine: SDTFEngine; switch (previous.type) { case 'SDTF': { tokenTree = previous.graph; sdtfEngine = createSDTFEngine(previous.graph); break; } case 'SDTF Engine': { tokenTree = previous.engine.renderJSONTree(); sdtfEngine = previous.engine; break; } default: { throw new SpecifyError({ errorKey: specifyErrors.PARSERS_ENGINE_INVALID_PARSER_INPUT.errorKey, publicMessage: `${ (previous as any).type } is not a valid input for the to-bitmap-file parser.`, }); } } if (outputOptions?.type !== 'directory') { throw new SpecifyError({ errorKey: specifyErrors.PARSERS_ENGINE_INVALID_OUTPUT_TYPE.errorKey, publicMessage: `The output type ${outputOptions?.type} is not supported by the to-bitmap-file parser.`, }); } const bitmapAssets = generateBitmapDataBoxAssets(tokenTree, toolbox); const directoryPath = outputOptions.directoryPath.endsWith('/') ? outputOptions.directoryPath : `${outputOptions.directoryPath}/`; let output: FilesOutput['files'] = []; const filenamesSet = new Set(); for (const asset of bitmapAssets) { const hasMoreThan1Mode = Object.keys(asset.token.$value).length > 1; const filenameTemplate = parserOptions?.filenameTemplate ? parserOptions?.filenameTemplate : hasMoreThan1Mode ? DEFAULT_FILENAME_TEMPLATE_WITH_MODES : DEFAULT_FILENAME_TEMPLATE_WITHOUT_MODES; const tokenState = sdtfEngine.query.getTokenState(new TreePath(asset.path)); if (!tokenState) throw new SpecifyError({ errorKey: specifyErrors.PARSERS_ENGINE_INVALID_PARSER_INPUT.errorKey, publicMessage: `Token path ${asset.path.join('.')} is not resolved.`, }); const filename = makeFilename(filenameTemplate, tokenState, asset.mode, asset.url); if (filenamesSet.has(filename)) { toolbox.populateMessage({ type: 'warning', content: `Duplicate filename "${filename}" from token "${tokenState.path.toString()}". File will not be added to result.`, errorKey: specifyErrors.PARSERS_ENGINE_PARSER_EXECUTION_FAILED.errorKey, }); } else { filenamesSet.add(filename); output.push({ path: `${directoryPath}${filename}`, content: { type: 'url', url: asset.url, }, }); } } toolbox.populateOutput({ type: 'files', files: output, }); return { type: 'bitmap', assets: bitmapAssets, }; };