"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getDefaultStyledComponentsConfig = exports.chainStaticAssetRule = exports.stringifyConfig = exports.getMetaTags = exports.getFavicon = exports.getInject = exports.getTitle = exports.getMinify = exports.getExtensions = exports.setConfig = exports.outputInspectConfigFiles = exports.getDefaultOutputConfig = exports.getDefaultPerformanceConfig = exports.getDefaultToolsConfig = exports.getDefaultSecurityConfig = exports.getDefaultHtmlConfig = exports.getDefaultSourceConfig = exports.getDefaultDevConfig = void 0;
/* eslint-disable max-lines */
const constants_1 = require("./constants");
const generateMetaTags_1 = require("./generateMetaTags");
const logger_1 = require("./logger");
const path_1 = require("path");
const lodash_1 = __importDefault(require("@modern-js/utils/lodash"));
const utils_1 = require("@modern-js/utils");
const getDefaultDevConfig = () => ({
    hmr: true,
    https: false,
    port: constants_1.DEFAULT_PORT,
    assetPrefix: '/',
    startUrl: false,
    progressBar: true,
    host: utils_1.DEFAULT_DEV_HOST,
});
exports.getDefaultDevConfig = getDefaultDevConfig;
const getDefaultSourceConfig = () => ({
    alias: {},
    preEntry: [],
    globalVars: {},
    compileJsDataURI: true,
});
exports.getDefaultSourceConfig = getDefaultSourceConfig;
const getDefaultHtmlConfig = () => ({
    inject: 'head',
    mountId: constants_1.DEFAULT_MOUNT_ID,
    crossorigin: false,
    disableHtmlFolder: false,
    scriptLoading: 'defer',
});
exports.getDefaultHtmlConfig = getDefaultHtmlConfig;
const getDefaultSecurityConfig = () => ({
    nonce: '',
    checkSyntax: false,
});
exports.getDefaultSecurityConfig = getDefaultSecurityConfig;
const getDefaultToolsConfig = () => ({
    tsChecker: {},
});
exports.getDefaultToolsConfig = getDefaultToolsConfig;
const getDefaultPerformanceConfig = () => ({
    buildCache: true,
    printFileSize: true,
    removeConsole: false,
    chunkSplit: {
        strategy: 'split-by-experience',
    },
});
exports.getDefaultPerformanceConfig = getDefaultPerformanceConfig;
const getDefaultOutputConfig = () => ({
    distPath: {
        root: constants_1.ROOT_DIST_DIR,
        js: constants_1.JS_DIST_DIR,
        css: constants_1.CSS_DIST_DIR,
        svg: constants_1.SVG_DIST_DIR,
        font: constants_1.FONT_DIST_DIR,
        html: constants_1.HTML_DIST_DIR,
        wasm: constants_1.WASM_DIST_DIR,
        image: constants_1.IMAGE_DIST_DIR,
        media: constants_1.MEDIA_DIST_DIR,
        server: constants_1.SERVER_DIST_DIR,
        worker: constants_1.SERVER_WORKER_DIST_DIR,
    },
    filename: {},
    charset: 'ascii',
    polyfill: 'entry',
    dataUriLimit: {
        svg: constants_1.DEFAULT_DATA_URL_SIZE,
        font: constants_1.DEFAULT_DATA_URL_SIZE,
        image: constants_1.DEFAULT_DATA_URL_SIZE,
        media: constants_1.DEFAULT_DATA_URL_SIZE,
    },
    legalComments: 'linked',
    cleanDistPath: true,
    svgDefaultExport: 'url',
    disableSvgr: false,
    disableCssExtract: false,
    disableMinimize: false,
    disableSourceMap: {
        js: false,
        css: undefined,
    },
    disableTsChecker: false,
    disableFilenameHash: false,
    disableCssModuleExtension: false,
    disableInlineRuntimeChunk: false,
    enableAssetFallback: false,
    enableAssetManifest: false,
    enableLatestDecorators: false,
    enableCssModuleTSDeclaration: false,
    enableInlineScripts: false,
    enableInlineStyles: false,
});
exports.getDefaultOutputConfig = getDefaultOutputConfig;
async function outputInspectConfigFiles({ builderConfig, bundlerConfigs, inspectOptions, builderOptions, configType, }) {
    const { fs, chalk, nanoid } = await Promise.resolve().then(() => __importStar(require('@modern-js/utils')));
    const { outputPath } = inspectOptions;
    const { target } = builderOptions;
    const files = [
        {
            path: (0, path_1.join)(outputPath, 'builder.config.js'),
            label: 'Builder Config',
            content: builderConfig,
        },
        ...bundlerConfigs.map((content, index) => {
            const suffix = Array.isArray(target) ? target[index] : target;
            const outputFile = `${configType}.config.${suffix}.js`;
            let outputFilePath = (0, path_1.join)(outputPath, outputFile);
            // if filename is conflict, add a random id to the filename.
            if (fs.existsSync(outputFilePath)) {
                outputFilePath = outputFilePath.replace(/\.js$/, `.${nanoid(4)}.js`);
            }
            return {
                path: outputFilePath,
                label: `${lodash_1.default.upperFirst(configType)} Config (${suffix})`,
                content,
            };
        }),
    ];
    await Promise.all(files.map(item => fs.outputFile(item.path, `module.exports = ${item.content}`)));
    const fileInfos = files
        .map(item => `  - ${chalk.bold.yellow(item.label)}: ${chalk.underline(item.path)}`)
        .join('\n');
    logger_1.logger.success(`Inspect config succeed, open following files to view the content: \n\n${fileInfos}\n`);
}
exports.outputInspectConfigFiles = outputInspectConfigFiles;
const setConfig = (config, path, value) => {
    lodash_1.default.set(config, path, value);
};
exports.setConfig = setConfig;
function getExtensions({ target = 'web', resolveExtensionPrefix, isTsProject, } = {}) {
    let extensions = [
        // only resolve .ts(x) files if it's a ts project
        // most projects are using TypeScript, resolve .ts(x) files first to reduce resolve time.
        ...(isTsProject ? ['.ts', '.tsx'] : []),
        '.js',
        '.jsx',
        '.mjs',
        '.json',
    ];
    // add an extra prefix to all extensions
    if (resolveExtensionPrefix) {
        const extensionPrefix = typeof resolveExtensionPrefix === 'string'
            ? resolveExtensionPrefix
            : resolveExtensionPrefix[target];
        if (extensionPrefix) {
            extensions = extensions.reduce((ret, ext) => [...ret, extensionPrefix + ext, ext], []);
        }
    }
    return extensions;
}
exports.getExtensions = getExtensions;
function getMinify(isProd, config) {
    if (config.output.disableMinimize || !isProd) {
        return false;
    }
    return {
        removeComments: false,
        useShortDoctype: true,
        keepClosingSlash: true,
        collapseWhitespace: true,
        removeRedundantAttributes: true,
        removeScriptTypeAttributes: true,
        removeStyleLinkTypeAttributes: true,
    };
}
exports.getMinify = getMinify;
function getTitle(entryName, config) {
    const { title, titleByEntries } = config.html;
    return (titleByEntries === null || titleByEntries === void 0 ? void 0 : titleByEntries[entryName]) || title || '';
}
exports.getTitle = getTitle;
function getInject(entryName, config) {
    const { inject, injectByEntries } = config.html;
    return (injectByEntries === null || injectByEntries === void 0 ? void 0 : injectByEntries[entryName]) || inject || true;
}
exports.getInject = getInject;
function getFavicon(entryName, config) {
    const { favicon, faviconByEntries } = config.html;
    return (faviconByEntries === null || faviconByEntries === void 0 ? void 0 : faviconByEntries[entryName]) || favicon;
}
exports.getFavicon = getFavicon;
async function getMetaTags(entryName, config) {
    const { meta, metaByEntries } = config.html;
    const metaOptions = {
        ...((metaByEntries === null || metaByEntries === void 0 ? void 0 : metaByEntries[entryName]) || meta || {}),
    };
    if (config.output.charset === 'utf8') {
        metaOptions.charset = { charset: 'utf-8' };
    }
    return (0, generateMetaTags_1.generateMetaTags)(metaOptions);
}
exports.getMetaTags = getMetaTags;
async function stringifyConfig(config, verbose) {
    const { default: WebpackChain } = await Promise.resolve().then(() => __importStar(require('../compiled/webpack-5-chain')));
    // webpackChain.toString can be used as a common stringify method
    const stringify = WebpackChain.toString;
    return stringify(config, { verbose });
}
exports.stringifyConfig = stringifyConfig;
const chainStaticAssetRule = ({ rule, maxSize, filename, assetType, issuer, }) => {
    // Rspack not support dataUrlCondition function
    // forceNoInline: "foo.png?__inline=false" or "foo.png?url",
    rule
        .oneOf(`${assetType}-asset-url`)
        .type('asset')
        .resourceQuery(/(__inline=false|url)/)
        .set('generator', {
        filename,
    })
        .set('issuer', issuer)
        .parser({
        dataUrlCondition: {
            maxSize: 0,
        },
    });
    // forceInline: "foo.png?inline" or "foo.png?__inline",
    rule
        .oneOf(`${assetType}-asset-inline`)
        .type('asset/inline')
        .resourceQuery(/inline/)
        .set('issuer', issuer);
    // default: when size < dataUrlCondition.maxSize will inline
    rule
        .oneOf(`${assetType}-asset`)
        .type('asset')
        .parser({
        dataUrlCondition: {
            maxSize,
        },
    })
        .set('generator', {
        filename,
    })
        .set('issuer', issuer);
};
exports.chainStaticAssetRule = chainStaticAssetRule;
const getDefaultStyledComponentsConfig = (isProd, ssr) => {
    return {
        ssr,
        // "pure" is used to improve dead code elimination in production.
        // we don't need to enable it in development because it will slow down the build process.
        pure: isProd,
        displayName: true,
        transpileTemplateLiterals: true,
    };
};
exports.getDefaultStyledComponentsConfig = getDefaultStyledComponentsConfig;
