UNPKG

@lmc-eu/spirit-analytics

Version:

Analytic tools for Spirit Design System

221 lines (211 loc) 7.58 kB
import { ROOT_PATH, _dirname, constants_exports, errorMessage, getOutputPath, getVersions, helpers_exports, infoMessage, react_scanner_config_default, spiritAdoptionProcessor_default, timestamp } from "./chunk-JUL5L4SB.js"; // src/cli.ts import sade from "sade"; import { fs as fs3, path as path3 } from "zx"; // src/scanner.ts import { fs as fs2 } from "zx"; // src/runner.ts import { path as path2 } from "zx"; // src/scanners/reactScanner.ts import scanner from "react-scanner"; async function reactScanner(config) { const output2 = await scanner.run({ ...config }); return output2; } // src/scanners/twigScanner.ts import { fs, glob, path } from "zx"; function getComponentsFromDirectory(directoryPath) { return fs.readdirSync(directoryPath).map((file) => `${file.charAt(0).toUpperCase()}${file.slice(1, -5)}`); } function getPathsFromYamlConfig(configFile) { const twigXConfigLines = fs.readFileSync(configFile, "utf8").split("\n"); return twigXConfigLines.filter((line) => line.trim().startsWith("-")).map( (line) => `${line.trim().substring(1).trim().replace(/"/g, "").replace(/^%kernel.\w+%/, ".")}/*.twig` ); } async function getLocalComponentsFromPaths(paths) { return glob(paths, (error, files) => { if (!error) { return files.map( (file) => path.basename(file).charAt(0).toUpperCase() + path.basename(file).slice(1, -5) ); } return []; }); } function determineModuleNameFromComponents(nodeName, localComponents, baseComponents) { if (baseComponents.includes(nodeName)) { return "@lmc-eu/spirit-web-twig"; } const pascalCaseRegex = /^([A-Z][a-z0-9]+)+$/; if (localComponents.includes(nodeName) || nodeName.match(pascalCaseRegex)) { return "local_component"; } return "html_element"; } function searchFileForComponents(file, localComponents, baseComponents) { const reStartTag = /<([a-zA-Z][a-zA-Z0-9]*)([^>]*)>/g; const reAttr = /([\w-]+)="?([^"]*)"?/g; const result = {}; const fileContent = fs.readFileSync(file, "utf-8"); let match = reStartTag.exec(fileContent); while (match !== null) { const [, nodeName, attrs] = match; const nodeStartPos = match.index; const numLineBreaks = fileContent.slice(0, nodeStartPos).match(/\n/g)?.length ?? 0; const moduleName = determineModuleNameFromComponents(nodeName, localComponents, baseComponents); const fullName = `${moduleName}:${nodeName}`; const node = { path: `${file}:${numLineBreaks + 1}`, props: {} }; attrs.replace(reAttr, (attrMatchString, name, value) => { node.props[name] = value.replace(/\n\s+/g, ""); return ""; }); if (!result[fullName]) { result[fullName] = []; } result[fullName].push(node); match = reStartTag.exec(fileContent); } return result; } function searchDirectoryForComponents(dir, localComponents, baseComponents, exclude) { let result = {}; if (!exclude.includes(path.basename(dir))) { const files = fs.readdirSync(dir); files.forEach((file) => { const filePath = path.join(dir, file); const fileStat = fs.lstatSync(filePath); if (fileStat.isDirectory()) { result = { ...result, ...searchDirectoryForComponents(filePath, localComponents, baseComponents, exclude) }; } else if (path.extname(filePath) === ".twig") { result = { ...result, ...searchFileForComponents(filePath, localComponents, baseComponents) }; } }); } return result; } var output = (data, destination) => { fs.mkdirSync(path.dirname(destination), { recursive: true }); fs.writeFileSync(destination, JSON.stringify(data, null, 2)); }; async function twigScanner(options) { const spiritComponents = getComponentsFromDirectory(path.resolve(process.cwd(), options.coreComponentsPath || "")); const twigXPaths = getPathsFromYamlConfig(path.resolve(process.cwd(), options.configFile || "")); const localComponents = await getLocalComponentsFromPaths(twigXPaths); const result = searchDirectoryForComponents( path.resolve(process.cwd(), options.rootPath || ""), localComponents, spiritComponents, options.exclude || [] ); output(result, path.resolve(process.cwd(), options.outputFile || "")); return result; } // src/runner.ts var getTrackedData = async ({ config, source, type }) => { const crawlFrom = path2.resolve(source) || path2.resolve(_dirname, ROOT_PATH); const spiritVersion = await getVersions(crawlFrom); let reactOutput = {}; let twigOutput = {}; if (type === "react" || type === null) { reactOutput = await reactScanner({ ...config.react, crawlFrom }); } if (type === "twig" || type === null) { twigOutput = await twigScanner({ ...config.twig, crawlFrom }); } return { spiritVersion, trackedData: { react: reactOutput, twig: twigOutput } }; }; var runner = (config, source, type) => getTrackedData({ config, source, type }); // src/scanner.ts var getRunnerCall = async ({ outputPath, config, source, type }) => { const result = await runner(config, source, type); if (outputPath) { fs2.writeFile(getOutputPath(outputPath, timestamp()), JSON.stringify(result, null, 2), "utf8").then(() => { infoMessage(`Successfully created ${timestamp()}.json file in the ${outputPath}`); }); } else { } }; async function scanner2({ source, outputPath, config, type }) { try { await getRunnerCall({ outputPath, config, source, type }); } catch (err) { errorMessage(` ${err}`); } } var scanner_default = scanner2; // src/cli.ts var packageJson = fs3.readJsonSync(path3.resolve(_dirname, "./package.json")); async function cli(args) { sade("analytics", true).version(packageJson.version).describe(packageJson.description).option("-s, --source", "Source to scan from").example("-s assets").option("-o, --output", "Output path for parsed files").example("-o path/to/folder").option("-c --config", "Path to scanner config").example("-c path/to/scanner.config.js").option("-t --type", "Type of scanner").example("-t react").action(async ({ output: output2, config, source, type }) => { let selectedConfig; if (config && !fs3.existsSync(config)) { errorMessage("Could not find config file"); process.exit(1); } else if (config && fs3.existsSync(config)) { infoMessage(`Using provided config file: ${config}`); selectedConfig = path3.resolve(process.cwd(), config); } else { infoMessage("Using default config file"); selectedConfig = path3.resolve(_dirname, "./spirit-analytics.config.js"); } if (output2 && !fs3.existsSync(output2)) { errorMessage("Path does not exists"); process.exit(1); } const { default: loadedConfig } = await import(selectedConfig); let selectedType = null; if (type) { selectedType = type; } if (source) { scanner_default({ source, outputPath: output2, config: loadedConfig, type: selectedType }); infoMessage(`Start scanning: ${source}`); } else { scanner_default({ source: path3.resolve(process.cwd(), ROOT_PATH), outputPath: output2, config: loadedConfig, type: selectedType }); infoMessage("Start scanning from default scope"); } }).parse(args); } // src/types.ts var types_exports = {}; export { cli, constants_exports as constants, helpers_exports as helpers, react_scanner_config_default as reactScannerConfig, scanner_default as scanner, spiritAdoptionProcessor_default as spiritAdoptionProcessor, types_exports as types };