"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 () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __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.Plugin = void 0;
const path_1 = __importDefault(require("path"));
const fs_extra_1 = __importDefault(require("fs-extra"));
const cheerio_1 = __importDefault(require("cheerio"));
const isString_1 = __importDefault(require("lodash/isString"));
const logger = __importStar(require("../utils/logger"));
const urlUtil = __importStar(require("../utils/urlUtil"));
require('../patches/htmlparser2');
const _ = { isString: isString_1.default };
const PLUGIN_OUTPUT_SITE_ASSET_FOLDER_NAME = 'plugins';
/**
 * Wrapper class around a loaded plugin module
 */
class Plugin {
    constructor(pluginName, pluginPath, pluginOptions, siteOutputPath) {
        this.pluginName = pluginName;
        /**
         * The plugin module
         */
        // eslint-disable-next-line global-require,import/no-dynamic-require
        this.plugin = require(pluginPath);
        this.pluginOptions = pluginOptions || {};
        // For resolving plugin asset source paths later
        this.pluginAbsolutePath = path_1.default.dirname(pluginPath);
        this.pluginAssetOutputPath = path_1.default.join(siteOutputPath, PLUGIN_OUTPUT_SITE_ASSET_FOLDER_NAME, path_1.default.basename(pluginPath, '.js'));
    }
    executeBeforeSiteGenerate() {
        if (this.plugin.beforeSiteGenerate) {
            this.plugin.beforeSiteGenerate(this.pluginOptions);
        }
    }
    /**
     * Resolves a resource specified as an attribute in a html asset tag
     * (eg. '<script>' or '<link>') provided by a plugin, and copies said asset
     * into the plugin's asset output folder.
     * Does nothing if the resource is a url.
     * @param assetElementHtml The asset element html, as a string, such as '<script src="...">'
     * @param tagName The name of the resource tag
     * @param attrName The attribute name where the resource is specified in the tag
     * @param baseUrl baseUrl of the site
     * @return String html of the element, with the attribute's asset resolved
     */
    _getResolvedAssetElement(assetElementHtml, tagName, attrName, baseUrl) {
        const $ = cheerio_1.default.load(assetElementHtml);
        const el = $(`${tagName}[${attrName}]`);
        el.attr(attrName, (_i, assetPath) => {
            if (!assetPath || !_.isString(assetPath) || urlUtil.isUrl(assetPath)) {
                return assetPath;
            }
            const srcPath = path_1.default.resolve(this.pluginAbsolutePath, assetPath);
            const srcBaseName = path_1.default.basename(srcPath);
            fs_extra_1.default.ensureDir(this.pluginAssetOutputPath)
                .then(() => {
                const outputPath = path_1.default.join(this.pluginAssetOutputPath, srcBaseName);
                fs_extra_1.default.copySync(srcPath, outputPath, { overwrite: false });
            })
                .catch(err => logger.error(`Failed to copy asset ${assetPath} for plugin ${this.pluginName}\n${err}`));
            return path_1.default.posix.join(`${baseUrl}/`, PLUGIN_OUTPUT_SITE_ASSET_FOLDER_NAME, this.pluginName, srcBaseName);
        });
        return $.html();
    }
    /**
     * Collect page content inserted by plugins
     */
    getPageNjkLinksAndScripts(frontmatter, content, baseUrl) {
        let links = [];
        let scripts = [];
        if (this.plugin.getLinks) {
            const pluginLinks = this.plugin.getLinks(this.pluginOptions, frontmatter, content);
            links = pluginLinks.map((linkHtml) => this._getResolvedAssetElement(linkHtml, 'link', 'href', baseUrl));
        }
        if (this.plugin.getScripts) {
            const pluginScripts = this.plugin.getScripts(this.pluginOptions, frontmatter, content);
            scripts = pluginScripts.map((scriptHtml) => this._getResolvedAssetElement(scriptHtml, 'script', 'src', baseUrl));
        }
        return {
            links,
            scripts,
        };
    }
    postRender(frontmatter, content) {
        if (this.plugin.postRender) {
            return this.plugin.postRender(this.pluginOptions, frontmatter, content);
        }
        return content;
    }
    processNode(node, config) {
        if (!this.plugin.processNode) {
            return;
        }
        this.plugin.processNode(this.pluginOptions, node, config);
    }
    postProcessNode(node, config) {
        if (!this.plugin.postProcessNode) {
            return;
        }
        this.plugin.postProcessNode(this.pluginOptions, node, config);
    }
    getTagConfig() {
        return this.plugin.tagConfig;
    }
}
exports.Plugin = Plugin;
//# sourceMappingURL=Plugin.js.map