{"version":3,"file":"anchor-tag-builder.js","sourceRoot":"","sources":["../../src/anchor-tag-builder.ts"],"names":[],"mappings":"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","sourcesContent":["import { HtmlTag } from './html-tag';\nimport { TruncateConfigObj } from './autolinker';\nimport { truncateSmart } from './truncate/truncate-smart';\nimport { truncateMiddle } from './truncate/truncate-middle';\nimport { truncateEnd } from './truncate/truncate-end';\nimport { AbstractMatch } from './match/abstract-match';\n\n/**\n * @protected\n * @class Autolinker.AnchorTagBuilder\n * @extends Object\n *\n * Builds anchor (&lt;a&gt;) tags for the Autolinker utility when a match is\n * found.\n *\n * Normally this class is instantiated, configured, and used internally by an\n * {@link Autolinker} instance, but may actually be used indirectly in a\n * {@link Autolinker#replaceFn replaceFn} to create {@link Autolinker.HtmlTag HtmlTag}\n * instances which may be modified before returning from the\n * {@link Autolinker#replaceFn replaceFn}. For example:\n *\n *     var html = Autolinker.link(\"Test google.com\", {\n *         replaceFn: function(match) {\n *             var tag = match.buildTag();  // returns an {@link Autolinker.HtmlTag} instance\n *             tag.setAttr('rel', 'nofollow');\n *\n *             return tag;\n *         }\n *     });\n *\n *     // generated html:\n *     //   Test <a href=\"http://google.com\" target=\"_blank\" rel=\"nofollow\">google.com</a>\n */\nexport class AnchorTagBuilder {\n    /**\n     * @cfg {Boolean} newWindow\n     * @inheritdoc Autolinker#newWindow\n     */\n    private readonly newWindow: boolean = false; // default value just to get the above doc comment in the ES5 output and documentation generator\n\n    /**\n     * @cfg {Object} truncate\n     * @inheritdoc Autolinker#truncate\n     */\n    private readonly truncate: TruncateConfigObj = {}; // default value just to get the above doc comment in the ES5 output and documentation generator\n\n    /**\n     * @cfg {String} className\n     * @inheritdoc Autolinker#className\n     */\n    private readonly className: string = ''; // default value just to get the above doc comment in the ES5 output and documentation generator\n\n    /**\n     * @method constructor\n     * @param {Object} [cfg] The configuration options for the AnchorTagBuilder instance, specified in an Object (map).\n     */\n    constructor(cfg: AnchorTagBuilderCfg = {}) {\n        this.newWindow = cfg.newWindow || false;\n        this.truncate = cfg.truncate || {};\n        this.className = cfg.className || '';\n    }\n\n    /**\n     * Generates the actual anchor (&lt;a&gt;) tag to use in place of the\n     * matched text, via its `match` object.\n     *\n     * @param match The Match instance to generate an anchor tag from.\n     * @return The HtmlTag instance for the anchor tag.\n     */\n    public build(match: AbstractMatch) {\n        return new HtmlTag({\n            tagName: 'a',\n            attrs: this.createAttrs(match),\n            innerHtml: this.processAnchorText(match.getAnchorText()),\n        });\n    }\n\n    /**\n     * Creates the Object (map) of the HTML attributes for the anchor (&lt;a&gt;)\n     *   tag being generated.\n     *\n     * @protected\n     * @param match The Match instance to generate an anchor tag from.\n     * @return A key/value Object (map) of the anchor tag's attributes.\n     */\n    protected createAttrs(match: AbstractMatch) {\n        const attrs: { [attrName: string]: string } = {\n            href: match.getAnchorHref(), // we'll always have the `href` attribute\n        };\n\n        const cssClass = this.createCssClass(match);\n        if (cssClass) {\n            attrs['class'] = cssClass;\n        }\n        if (this.newWindow) {\n            attrs['target'] = '_blank';\n            attrs['rel'] = 'noopener noreferrer'; // Issue #149. See https://mathiasbynens.github.io/rel-noopener/\n        }\n\n        if (this.truncate.length && this.truncate.length < match.getAnchorText().length) {\n            attrs['title'] = match.getAnchorHref();\n        }\n\n        return attrs;\n    }\n\n    /**\n     * Creates the CSS class that will be used for a given anchor tag, based on\n     * the `matchType` and the {@link #className} config.\n     *\n     * Example returns:\n     *\n     * - \"\"                                      // no {@link #className}\n     * - \"myLink myLink-url\"                     // url match\n     * - \"myLink myLink-email\"                   // email match\n     * - \"myLink myLink-phone\"                   // phone match\n     * - \"myLink myLink-hashtag\"                 // hashtag match\n     * - \"myLink myLink-mention myLink-twitter\"  // mention match with Twitter service\n     *\n     * @protected\n     * @param match The Match instance to generate an\n     *   anchor tag from.\n     * @return The CSS class string for the link. Example return:\n     *   \"myLink myLink-url\". If no {@link #className} was configured, returns\n     *   an empty string.\n     */\n    protected createCssClass(match: AbstractMatch): string {\n        const className = this.className;\n\n        if (!className) {\n            return '';\n        } else {\n            const returnClasses = [className],\n                cssClassSuffixes = match.getCssClassSuffixes();\n\n            for (let i = 0, len = cssClassSuffixes.length; i < len; i++) {\n                returnClasses.push(className + '-' + cssClassSuffixes[i]);\n            }\n            return returnClasses.join(' ');\n        }\n    }\n\n    /**\n     * Processes the `anchorText` by truncating the text according to the\n     * {@link #truncate} config.\n     *\n     * @private\n     * @param anchorText The anchor tag's text (i.e. what will be\n     *   displayed).\n     * @return The processed `anchorText`.\n     */\n    private processAnchorText(anchorText: string): string {\n        anchorText = this.doTruncate(anchorText);\n\n        return anchorText;\n    }\n\n    /**\n     * Performs the truncation of the `anchorText` based on the {@link #truncate}\n     * option. If the `anchorText` is longer than the length specified by the\n     * {@link #truncate} option, the truncation is performed based on the\n     * `location` property. See {@link #truncate} for details.\n     *\n     * @private\n     * @param anchorText The anchor tag's text (i.e. what will be\n     *   displayed).\n     * @return The truncated anchor text.\n     */\n    private doTruncate(anchorText: string): string {\n        const truncate = this.truncate;\n        if (!truncate.length) return anchorText;\n\n        const truncateLength = truncate.length,\n            truncateLocation = truncate.location;\n\n        if (truncateLocation === 'smart') {\n            return truncateSmart(anchorText, truncateLength);\n        } else if (truncateLocation === 'middle') {\n            return truncateMiddle(anchorText, truncateLength);\n        } else {\n            return truncateEnd(anchorText, truncateLength);\n        }\n    }\n}\n\nexport interface AnchorTagBuilderCfg {\n    newWindow?: boolean;\n    truncate?: TruncateConfigObj;\n    className?: string;\n}\n"]}