UNPKG

@sitecore-jss/sitecore-jss

Version:

This module is provided as a part of Sitecore JavaScript Rendering SDK. It contains the core JSS APIs (layout service) and utilities.

115 lines (114 loc) 4.87 kB
import unescape from 'lodash.unescape'; import URL from 'url-parse'; // finds an img tag with HTML attributes const imgTagRegex = /<img([^>]+)\/>/i; // finds all the HTML attributes in a string const htmlAttrsRegex = /([^=\s]+)(="([^"]*)")?/gi; // finds the Sitecore media URL prefix const mediaUrlPrefixRegex = /\/([-~]{1})\/media\//i; /** * Makes a request to Sitecore Content Service for the specified item path. * @param {string} editorMarkup the markup to parse * @returns {object | null} found image tag; null in case if not found */ export const findEditorImageTag = (editorMarkup) => { // match the tag const tagMatch = editorMarkup.match(imgTagRegex); if (!tagMatch || tagMatch.length < 2) { return null; } // find the attrs and turn them into a Map const attrs = {}; let match = htmlAttrsRegex.exec(tagMatch[1]); while (match !== null) { attrs[match[1]] = unescape(match[3]); match = htmlAttrsRegex.exec(tagMatch[1]); } return { imgTag: tagMatch[0], attrs, }; }; /** * Get required query string params which should be merged with user params * @param {object} qs layout service parsed query string * @returns {object} requiredParams */ export const getRequiredParams = (qs) => { const { rev, db, la, vs, ts } = qs; return { rev, db, la, vs, ts }; }; /** * Replace `/~/media` or `/-/media` with `/~/jssmedia` or `/-/jssmedia`, respectively. * Can use `mediaUrlPrefix` in order to use a custom prefix. * @param {string} url The URL to replace the media URL prefix in * @param {RegExp} [mediaUrlPrefix] The regex to match the media URL prefix * @returns {string} The URL with the media URL prefix replaced */ export const replaceMediaUrlPrefix = (url, mediaUrlPrefix = mediaUrlPrefixRegex) => { const parsed = URL(url, {}, true); const match = mediaUrlPrefix.exec(parsed.pathname); if (match && match.length > 1) { // regex will provide us with /-/ or /~/ type parsed.set('pathname', parsed.pathname.replace(mediaUrlPrefix, `/${match[1]}/jssmedia/`)); } return parsed.toString(); }; /** * Prepares a Sitecore media URL with `params` for use by the JSS media handler. * This is done by replacing `/~/media` or `/-/media` with `/~/jssmedia` or `/-/jssmedia`, respectively. * Provided `params` are used as the querystring parameters for the media URL. * Can use `mediaUrlPrefix` in order to use a custom prefix. * If no `params` are sent, the original media URL is returned. * @param {string} url The URL to prepare * @param {object} [params] The querystring parameters to use * @param {RegExp} [mediaUrlPrefix] The regex to match the media URL prefix * @returns {string} The prepared URL */ export const updateImageUrl = (url, params, mediaUrlPrefix = mediaUrlPrefixRegex) => { if (!params || Object.keys(params).length === 0) { // if params aren't supplied, no need to run it through JSS media handler return url; } // polyfill node `global` in browser to workaround https://github.com/unshiftio/url-parse/issues/150 if (typeof window !== 'undefined' && !window.global) { window.global = {}; } const parsed = URL(replaceMediaUrlPrefix(url, mediaUrlPrefix), {}, true); const requiredParams = getRequiredParams(parsed.query); const query = Object.assign({}, params); Object.entries(requiredParams).forEach(([key, param]) => { if (param) { query[key] = param; } }); parsed.set('query', query); return parsed.toString(); }; /** * Receives an array of `srcSet` parameters that are iterated and used as parameters to generate * a corresponding set of updated Sitecore media URLs via @see updateImageUrl. The result is a comma-delimited * list of media URLs with respective dimension parameters. * @example * // returns '/ipsum.jpg?h=1000&w=1000 1000w, /ipsum.jpg?mh=250&mw=250 250w' * getSrcSet('/ipsum.jpg', [{ h: 1000, w: 1000 }, { mh: 250, mw: 250 } ]) * More information about `srcSet`: {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img} * @param {string} url The URL to prepare * @param {Array} srcSet The array of parameters to use * @param {object} [imageParams] The querystring parameters to use * @param {RegExp} [mediaUrlPrefix] The regex to match the media URL prefix * @returns {string} The prepared URL */ export const getSrcSet = (url, srcSet, imageParams, mediaUrlPrefix) => { return srcSet .map((params) => { const newParams = Object.assign(Object.assign({}, imageParams), params); const imageWidth = newParams.w || newParams.mw; if (!imageWidth) { return null; } return `${updateImageUrl(url, newParams, mediaUrlPrefix)} ${imageWidth}w`; }) .filter((value) => value) .join(', '); };