bandcamp.jsx 3.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
import React from 'react';

/**
 * Regular expressions for detecting and validating provider URLs
 * @type {{htmlReplacement: RegExp, main: RegExp, sanitize: RegExp}}
 */
const regex = {
    sanitize: /^https:\/\/bandcamp\.com\/EmbeddedPlayer\/(album=.*)/i,
};
export default regex;

/**
 * Configuration for HTML iframe's `sandbox` attribute
 * @type {useSandbox: boolean, sandboxAttributes: string[]}
 */
export const sandboxConfig = {
    useSandbox: false,
    sandboxAttributes: [],
};

export function getIframeDimensions(...args) {
    const [, idOrUrl] = args;
    const baseHeight = 120;
    const tracklistHeight = 155;
    const largeArtworkHeight = 580;
    const hasLargeArtwork = idOrUrl.indexOf('artwork=large') !== -1;
    const tracklistEnabled = idOrUrl.indexOf('tracklist=true') !== -1;

    let height = baseHeight;

    if (hasLargeArtwork) {
        height += largeArtworkHeight;
    }

    if (tracklistEnabled) {
        height += tracklistHeight;
        if (hasLargeArtwork) {
            height += baseHeight;
        }
    }

    return {
        width: 700,
        height,
    };
}

/**
 * Check if the iframe code in the post editor is to an allowed URL
 * <iframe style="border: 0; width: 100%; height: 120px;" src="https://bandcamp.com/EmbeddedPlayer/album=1820259073/size=large/bgcol=ffffff/linkcol=0687f5/tracklist=true/artwork=small/transparent=true/" seamless><a href="https://bluetech.bandcamp.com/album/tomorrow">Tomorrow by Steve Roach</a></iframe>
 * <iframe style="border: 0; width: 100%; height: 120px;" src="https://bandcamp.com/EmbeddedPlayer/album=1820259073/size=large/bgcol=ffffff/linkcol=0687f5/tracklist=true/artwork=small/track=266656541/transparent=true/" seamless><a href="https://bluetech.bandcamp.com/album/tomorrow">Tomorrow by Steve Roach</a></iframe>
 * @param url
 * @returns {boolean|*}
 */
export function validateIframeUrl(url) {
    const match = url.match(regex.sanitize);

    if (!match || match.length !== 2) {
        return false;
    }

    return 'https://bandcamp.com/EmbeddedPlayer/' + match[1];
}

/**
 * Rewrites the embedded URL to a normalized format
 * @param url
 * @returns {string|boolean}
 */
export function normalizeEmbedUrl(url) {
    const match = url.match(regex.sanitize);

    if (match && match.length >= 2) {
        return `https://bandcamp.com/EmbeddedPlayer/${match[1]}`;
    }

    return false;
}

/**
 * Replaces the URL with a custom Markdown for embedded players
 * @param child
 * @param links
 * @returns {*}
 */
export function embedNode(child) {
    return child;
}

/**
 * Generates the Markdown/HTML code to override the detected URL with an iFrame
 * @param idx
 * @param id
 * @param width
 * @param height
 * @param startTime
 * @returns {*}
 */
export function genIframeMd(idx, id, width, height) {
    const url = `https://bandcamp.com/EmbeddedPlayer/${id}`;

    let sandbox = sandboxConfig.useSandbox;
    if (sandbox) {
        if (
            Object.prototype.hasOwnProperty.call(
                sandboxConfig,
                'sandboxAttributes'
            )
        ) {
            sandbox = sandboxConfig.sandboxAttributes.join(' ');
        }
    }
    const iframeProps = {
        src: url,
        width,
        height,
        frameBorder: '0',
        webkitallowfullscreen: 'webkitallowfullscreen',
        mozallowfullscreen: 'mozallowfullscreen',
        allowFullScreen: 'allowFullScreen',
    };
    if (sandbox) {
        iframeProps.sandbox = sandbox;
    }

    return (
        <div key={`bandcamp-${id}-${idx}`} className="videoWrapper">
            <iframe
                title="bandcamp.com embedded player"
                // eslint-disable-next-line react/jsx-props-no-spreading
                {...iframeProps}
            />
        </div>
    );
}