SockDrawer/SockBot

View on GitHub
providers/nodebb/format.js

Summary

Maintainability
A
1 hr
Test Coverage
'use strict';

/**
 * stringify a parameter.
 *
 * falsy things become empty string, everything else is toStringed
 *
 * @private
 * @param {*} text thing to stringify
 * @returns {string} stringified text
 */
function stringify(text) {
    return `${text || ''}`;
}

/**
 * Apply a prefix (and suffix) to a text
 *
 * @private
 * @param {string} prefix Prefix to apply
 * @param {*} text Text to wrap
 * @param {string} [suffix=''] Suffix to apply
 * @returns {string} wrapped Text
 */
function prefixifier(prefix, text, suffix) {
    text = stringify(text);
    if (!text) {
        return '';
    }
    suffix = suffix || '';
    return prefix + text.replace(/^\s+|\s+$/g, '') + suffix;
}

/**
 * Generate a permalink for a post
 *
 * @param {!number} postId Id or the post to url
 * @returns {string} Absolute URL for post
 */
exports.urlForPost = function postLink(postId) {
    return prefixifier('/post/', postId);
};

/**
 * Generate a link for a topic
 *
 * @param {!number} topicId Id of the topic to url
 * @param {string} [topicSlug] Slug of the topic to url
 * @param {number} [postIndex] Index of the post to url to in topic
 * @returns {string} Absolute URL for topic
 */
exports.urlForTopic = function linkTopic(topicId, topicSlug, postIndex) {
    if (!topicId || !`${topicId}`) {
        return '';
    }
    if (typeof topicSlug === 'number' && !postIndex) {
        // No slug provided. i can deal with that
        postIndex = topicSlug;
        topicSlug = 'topic';
    }
    if (!postIndex) {
        postIndex = '';
    }
    if (!topicSlug) {
        topicSlug = '';
    }
    const url = `/topic/${topicId}/${topicSlug}/${postIndex}`;
    return url.replace(/\/*$/, '');
};

/**
 * Turn input text into a forum quote
 *
 * @param {!string} text Text to quote
 * @param {string} [quotedUser] User who said the quote
 * @param {string} [contextUrl] Url to the quoted post
 * @param {string} [contextTitle] Title of the quote context link
 * @returns {string} quoted text, with attribution if username provided
 */
exports.quoteText = function quoteText(text, quotedUser, contextUrl, contextTitle) {
    const quote = stringify(text),
        user = stringify(quotedUser),
        url = stringify(contextUrl),
        title = stringify(contextTitle);
    if (!quote) {
        return '';
    }
    const parts = quote.split(/\n/).map((line) => `> ${line}`);
    if (user) {
        let attribution = `@${user}`;
        if (url) {
            if (title) {
                attribution += ` said in [${title}](${url}):`;
            } else {
                attribution += ` [said](${url}):`;
            }
        } else {
            attribution += ' said:';
        }
        parts.unshift(attribution);
    }
    return parts.join('\n');
};

/**
 * Construct a result consisting of two data points in three parts
 *
 * @private
 * @param {string} before Prefix
 * @param {*} item1 First part
 * @param {string} defaultItem1 Value to use for item1 when item1 is falsy
 * @param {string} middle part to go between item1 and item2
 * @param {*} item2 Second Part
 * @param {string} after Suffix
 * @returns {string} Formatted thing
 */
function threeParts(before, item1, defaultItem1, middle, item2, after) {
    item2 = stringify(item2);
    item1 = stringify(item1);
    if (!item2) {
        return '';
    }
    return before + (item1 || defaultItem1) + middle + item2 + after;
}

/**
 * Generate a hyperlink
 *
 * @param {!string} url URL to link to
 * @param {string} linkText Link Text to display
 * @returns {string} Linkified url
 */
exports.link = function link(url, linkText) {
    return threeParts('[', linkText, 'Click Me.', '](', url, ')');
};

/**
 * Generate an image
 *
 * @param {!string} url Image URL
 * @param {string} titleText Title text to display
 * @returns {string} Image incantation
 */
exports.image = function image(url, titleText) {
    url = stringify(url);
    titleText = stringify(titleText);
    if (!url) {
        return '';
    }
    if (!titleText) {
        const parts = url.split('/');
        titleText = parts[parts.length - 1];
    }
    return `![${titleText}](${url} "${titleText.replace(/"/g, '')}")`;
};

/**
 * Spoiler something
 *
 * @param {!string} body Spoiler body
 * @param {string} title spoiler title to display
 * @returns {string} spoilered text
 */
exports.spoiler = function spoiler(body, title) {
    return threeParts('<details>\n<summary>\n', title, 'SPOILER!', '\n</summary>\n\n', body, '\n\n</details>');
};

/**
 * Format text as bold.
 *
 * @param {!string} text Input text
 * @returns {string} Bolded Text
 */

exports.bold = function bold(text) {
    return prefixifier('**', text, '**');
};

/**
 * Format text as italic.
 *
 * @param {!string} text Input text
 * @returns {string} Italiced Text
 */

exports.italic = function italic(text) {
    return prefixifier('*', text, '*');
};

/**
 * Format text as bold italic.
 *
 * @param {!string} text Input text
 * @returns {string} Bolded and italiced Text
 */

exports.bolditalic = function bolditalic(text) {
    return prefixifier('***', text, '***');
};

/**
 * Format text as a first level header.
 *
 * @param {!string} text Header text
 * @returns {string} Headered Text
 */

exports.header1 = function header1(text) {
    return prefixifier('# ', text);
};

/**
 * Format text as a second level header.
 *
 * @param {!string} text Header text
 * @returns {string} Headered Text
 */

exports.header2 = function header2(text) {
    return prefixifier('## ', text);
};

/**
 * Format text as a third level header.
 *
 * @param {!string} text Header text
 * @returns {string} Headered Text
 */

exports.header3 = function header3(text) {
    return prefixifier('### ', text);
};

/**
 * Format text as a fourth level header.
 *
 * @param {!string} text Header text
 * @returns {string} Headered Text
 */

exports.header4 = function header4(text) {
    return prefixifier('#### ', text);
};

/**
 * Format text as a fifth level header.
 *
 * @param {!string} text Header text
 * @returns {string} Headered Text
 */

exports.header5 = function header5(text) {
    return prefixifier('##### ', text);
};

/**
 * Format text as a sixth level header.
 *
 * @param {!string} text Header text
 * @returns {string} Headered Text
 */

exports.header6 = function header6(text) {
    return prefixifier('###### ', text);
};

/**
 * Format text as a preformatted block
 *
 * @param {!string} text The text
 * @returns {string} Text in a preformat block
 */
/* eslint-disable prefer-template */
exports.preformat = function preformat(text) {
    if (text.indexOf('\n') > -1) {
        return '```\n' + text + '\n```';
    }
    return '`' + text + '`';
};
/* eslint-enable prefer-template */

/**
 * Format text with a strikethrough effect
 *
 * @param {!string} text The text to strike out
 * @returns {string} The stricken text
 */
exports.strikethrough = function strikethrough(text) {
    return prefixifier('~~', text, '~~');
};

/**
 * Format text as a list of items
 *
 * @param {!string} items An array of strings to format as a list
 * @returns {string} The list
 */
exports.list = function list(items) {
    return items.map((item) => `\n- ${item}`).join('');
};