diff --git a/packages/extensions/venia-sample-language-packs/i18n/fr_FR.json b/packages/extensions/venia-sample-language-packs/i18n/fr_FR.json index db5c2a019f..5f6380ab25 100644 --- a/packages/extensions/venia-sample-language-packs/i18n/fr_FR.json +++ b/packages/extensions/venia-sample-language-packs/i18n/fr_FR.json @@ -134,7 +134,6 @@ "createWishlist.dialogTitle": "Nouvelle liste de favoris", "createWishlist.handleCreateListText": "Créer une liste", "createWishlist.listName": "Nom de la liste", - "customAttributes.title": "Détails", "Customer Service": "Service à la clientèle", "customerForm.defaultShipping": "Faites-en mon adresse par défaut", "customerForm.formMessage": "L'adresse de livraison que vous entrez sera enregistrée dans votre carnet d'adresses et définie par défaut pour vos futurs achats.", @@ -312,6 +311,7 @@ "productFullDetail.errorToken": "Un problème est survenu avec votre panier. Veuillez vous reconnecter et réessayer d'ajouter l'élément.", "productFullDetail.errorUnknown": "Impossible d'ajouter l'article au panier. Veuillez vérifier les options requises et réessayer.", "productFullDetail.productDescription": "Description du produit", + "productFullDetail.details": "Détails", "productList.each": " ch.", "productList.outOfStock": "en rupture de stock", "productList.quantity": "Qté : {quantity}", diff --git a/packages/pagebuilder/lib/ContentTypes/Banner/banner.js b/packages/pagebuilder/lib/ContentTypes/Banner/banner.js index 4f9b3b0c05..e38907e106 100644 --- a/packages/pagebuilder/lib/ContentTypes/Banner/banner.js +++ b/packages/pagebuilder/lib/ContentTypes/Banner/banner.js @@ -3,7 +3,7 @@ import defaultClasses from './banner.module.css'; import { useStyle } from '@magento/venia-ui/lib/classify'; import { arrayOf, bool, oneOf, shape, string, func, object } from 'prop-types'; import Button from '@magento/venia-ui/lib/components/Button/button'; -import resolveLinkProps from '../../resolveLinkProps'; +import resolveLinkProps from '@magento/peregrine/lib/util/resolveLinkProps'; import { Link, useHistory } from 'react-router-dom'; import resourceUrl from '@magento/peregrine/lib/util/makeUrl'; import useIntersectionObserver from '@magento/peregrine/lib/hooks/useIntersectionObserver'; diff --git a/packages/pagebuilder/lib/ContentTypes/ButtonItem/buttonItem.js b/packages/pagebuilder/lib/ContentTypes/ButtonItem/buttonItem.js index 17efb7ac31..b2facf581d 100644 --- a/packages/pagebuilder/lib/ContentTypes/ButtonItem/buttonItem.js +++ b/packages/pagebuilder/lib/ContentTypes/ButtonItem/buttonItem.js @@ -4,7 +4,7 @@ import { useHistory } from 'react-router-dom'; import { useStyle } from '@magento/venia-ui/lib/classify'; import Button from '@magento/venia-ui/lib/components/Button/button'; -import resolveLinkProps from '../../resolveLinkProps'; +import resolveLinkProps from '@magento/peregrine/lib/util/resolveLinkProps'; import defaultClasses from './buttonItem.module.css'; /** diff --git a/packages/pagebuilder/lib/ContentTypes/Image/image.js b/packages/pagebuilder/lib/ContentTypes/Image/image.js index 1d775b4e31..7b7b2b74d0 100644 --- a/packages/pagebuilder/lib/ContentTypes/Image/image.js +++ b/packages/pagebuilder/lib/ContentTypes/Image/image.js @@ -2,7 +2,7 @@ import React from 'react'; import defaultClasses from './image.module.css'; import { arrayOf, bool, oneOf, shape, string, number } from 'prop-types'; import { Link } from 'react-router-dom'; -import resolveLinkProps from '../../resolveLinkProps'; +import resolveLinkProps from '@magento/peregrine/lib/util/resolveLinkProps'; import { useStyle } from '@magento/venia-ui/lib/classify'; import resourceUrl from '@magento/peregrine/lib/util/makeUrl'; diff --git a/packages/pagebuilder/lib/ContentTypes/Text/text.js b/packages/pagebuilder/lib/ContentTypes/Text/text.js index 056b31fb17..9841a54325 100644 --- a/packages/pagebuilder/lib/ContentTypes/Text/text.js +++ b/packages/pagebuilder/lib/ContentTypes/Text/text.js @@ -5,7 +5,9 @@ import defaultClasses from './text.module.css'; import { useHistory } from 'react-router-dom'; import handleHtmlContentClick from '../../handleHtmlContentClick'; -const toHTML = str => ({ __html: str }); +import htmlStringImgUrlConverter from '@magento/peregrine/lib/util/htmlStringImgUrlConverter'; + +const toHTML = str => ({ __html: htmlStringImgUrlConverter(str) }); /** * Page Builder Text component. diff --git a/packages/peregrine/lib/talons/ProductFullDetail/useProductFullDetail.js b/packages/peregrine/lib/talons/ProductFullDetail/useProductFullDetail.js index 325554a4f1..302b91fa51 100644 --- a/packages/peregrine/lib/talons/ProductFullDetail/useProductFullDetail.js +++ b/packages/peregrine/lib/talons/ProductFullDetail/useProductFullDetail.js @@ -460,6 +460,7 @@ export const useProductFullDetail = props => { // Normalization object for product details we need for rendering. const productDetails = { description: product.description, + shortDescription: product.short_description, name: product.name, price: productPrice, sku: product.sku diff --git a/packages/peregrine/lib/talons/RootComponents/Product/productDetailFragment.gql.js b/packages/peregrine/lib/talons/RootComponents/Product/productDetailFragment.gql.js index 764c883001..cbd4df37e0 100644 --- a/packages/peregrine/lib/talons/RootComponents/Product/productDetailFragment.gql.js +++ b/packages/peregrine/lib/talons/RootComponents/Product/productDetailFragment.gql.js @@ -13,6 +13,9 @@ export const ProductDetailsFragment = gql` description { html } + short_description { + html + } id uid # eslint-disable-next-line @graphql-eslint/require-id-when-available diff --git a/packages/peregrine/lib/util/__tests__/resolveLinkProps.spec.js b/packages/peregrine/lib/util/__tests__/resolveLinkProps.spec.js new file mode 100644 index 0000000000..4f444774a2 --- /dev/null +++ b/packages/peregrine/lib/util/__tests__/resolveLinkProps.spec.js @@ -0,0 +1,53 @@ +import resolveLinkProps from '../resolveLinkProps'; + +describe('resolve to internal link', () => { + process.env.MAGENTO_BACKEND_URL = 'http://magento.com/'; + + test('when base url matches', () => { + const linkProps = resolveLinkProps('http://magento.com/cms-page'); + expect(linkProps).toEqual({ + to: '/cms-page' + }); + }); + + test('when base url matches product URL', () => { + const linkProps = resolveLinkProps( + 'http://magento.com/product-page.html' + ); + expect(linkProps).toEqual({ + to: '/product-page.html' + }); + }); + + test('with root-relative url', () => { + const linkProps = resolveLinkProps('/cms-page'); + expect(linkProps).toEqual({ + to: '/cms-page' + }); + }); + + test('with relative url', () => { + const linkProps = resolveLinkProps('cms-page'); + expect(linkProps).toEqual({ + to: '/cms-page' + }); + }); +}); + +test('resolve to external anchor if external link', () => { + process.env.MAGENTO_BACKEND_URL = 'http://magento.com/'; + const linkProps = resolveLinkProps( + 'http://not-magento.com/product-page.html' + ); + expect(linkProps).toEqual({ + href: 'http://not-magento.com/product-page.html' + }); +}); + +test('return original input if input is invalid', () => { + process.env.MAGENTO_BACKEND_URL = null; + const linkProps = resolveLinkProps(null); + expect(linkProps).toEqual({ + href: null + }); +}); diff --git a/packages/peregrine/lib/util/htmlStringImgUrlConverter.js b/packages/peregrine/lib/util/htmlStringImgUrlConverter.js new file mode 100644 index 0000000000..96779fb97c --- /dev/null +++ b/packages/peregrine/lib/util/htmlStringImgUrlConverter.js @@ -0,0 +1,26 @@ +import makeUrl from './makeUrl'; +import resolveLinkProps from './resolveLinkProps'; + +/** + * Modifies html string images to use makeUrl as source and resolves links to use internal path. + * + * @param {string} htmlString - the html string to be updated + * @return {string} + */ +const htmlStringImgUrlConverter = htmlString => { + const temporaryElement = document.createElement('div'); + temporaryElement.innerHTML = htmlString; + for (const imgElement of temporaryElement.getElementsByTagName('img')) { + imgElement.src = makeUrl(imgElement.src, { + type: 'image-wysiwyg', + quality: 85 + }); + } + for (const linkElement of temporaryElement.getElementsByTagName('a')) { + const linkProps = resolveLinkProps(linkElement.href); + linkElement.href = linkProps.to || linkProps.href; + } + return temporaryElement.innerHTML; +}; + +export default htmlStringImgUrlConverter; diff --git a/packages/peregrine/lib/util/resolveLinkProps.js b/packages/peregrine/lib/util/resolveLinkProps.js new file mode 100644 index 0000000000..f8262f1b42 --- /dev/null +++ b/packages/peregrine/lib/util/resolveLinkProps.js @@ -0,0 +1,25 @@ +/** + * Resolve link properties + * + * @param {string} link + */ +export default link => { + let isExternalUrl; + const linkProps = {}; + + try { + const baseUrlObj = new URL(process.env.MAGENTO_BACKEND_URL); + const urlObj = new URL(link, baseUrlObj); + isExternalUrl = baseUrlObj.host !== urlObj.host; + + if (isExternalUrl) { + linkProps['href'] = link; + } else { + linkProps['to'] = urlObj.pathname; + } + } catch (e) { + linkProps['href'] = link; + } + + return linkProps; +}; diff --git a/packages/venia-ui/i18n/en_US.json b/packages/venia-ui/i18n/en_US.json index 330e88de57..ec3d0f7c6e 100644 --- a/packages/venia-ui/i18n/en_US.json +++ b/packages/venia-ui/i18n/en_US.json @@ -155,7 +155,6 @@ "createWishlistForm.privateRadio": "Private", "createWishlistForm.publicRadio": "Public", "createWishlistForm.saveButton": "Save", - "customAttributes.title": "Details", "Customer Service": "Customer Service", "customerForm.defaultShipping": "Make this my default address", "customerForm.formMessage": "The shipping address you enter will be saved to your address book and set as your default for future purchases.", @@ -357,6 +356,7 @@ "productFullDetail.errorToken": "There was a problem with your cart. Please sign in again and try adding the item once more.", "productFullDetail.errorUnknown": "Could not add item to cart. Please check required options and try again.", "productFullDetail.productDescription": "Product Description", + "productFullDetail.details": "Details", "productFullDetail.unavailableProduct": "This product is currently unavailable for purchase.", "productImageCarousel.previousButtonAriaLabel": "Previous Image", "productImageCarousel.nextButtonAriaLabel": "Next Image", diff --git a/packages/venia-ui/lib/components/ProductFullDetail/CustomAttributes/AttributeType/Select/select.module.css b/packages/venia-ui/lib/components/ProductFullDetail/CustomAttributes/AttributeType/Select/select.module.css index 14e3f64e1e..dc79aa720f 100644 --- a/packages/venia-ui/lib/components/ProductFullDetail/CustomAttributes/AttributeType/Select/select.module.css +++ b/packages/venia-ui/lib/components/ProductFullDetail/CustomAttributes/AttributeType/Select/select.module.css @@ -9,5 +9,5 @@ } .contentHtml { - composes: block from global; + composes: inline-block from global; } diff --git a/packages/venia-ui/lib/components/ProductFullDetail/CustomAttributes/AttributeType/Text/text.module.css b/packages/venia-ui/lib/components/ProductFullDetail/CustomAttributes/AttributeType/Text/text.module.css index 14e3f64e1e..dc79aa720f 100644 --- a/packages/venia-ui/lib/components/ProductFullDetail/CustomAttributes/AttributeType/Text/text.module.css +++ b/packages/venia-ui/lib/components/ProductFullDetail/CustomAttributes/AttributeType/Text/text.module.css @@ -9,5 +9,5 @@ } .contentHtml { - composes: block from global; + composes: inline-block from global; } diff --git a/packages/venia-ui/lib/components/ProductFullDetail/CustomAttributes/AttributeType/Textarea/textarea.js b/packages/venia-ui/lib/components/ProductFullDetail/CustomAttributes/AttributeType/Textarea/textarea.js index 06df5feed1..3ebdb69972 100644 --- a/packages/venia-ui/lib/components/ProductFullDetail/CustomAttributes/AttributeType/Textarea/textarea.js +++ b/packages/venia-ui/lib/components/ProductFullDetail/CustomAttributes/AttributeType/Textarea/textarea.js @@ -18,11 +18,16 @@ import defaultClasses from './textarea.module.css'; */ const Textarea = props => { const classes = useStyle(defaultClasses, props.classes); - const { attribute_metadata = {}, entered_attribute_value = {} } = props; + const { + attribute_metadata = {}, + entered_attribute_value = {}, + showLabels = true + } = props; - const attributeLabel = attribute_metadata.label ? ( -
{attribute_metadata.label}
- ) : null; + const attributeLabel = + attribute_metadata.label && showLabels ? ( +
{attribute_metadata.label}
+ ) : null; let attributeContent; if (entered_attribute_value.value) { @@ -30,6 +35,7 @@ const Textarea = props => { if (isHtml) { // TODO: Get decoded wysiwyg widgets from GraphQl + attributeContent = (
diff --git a/packages/venia-ui/lib/components/ProductFullDetail/CustomAttributes/AttributeType/attributeType.js b/packages/venia-ui/lib/components/ProductFullDetail/CustomAttributes/AttributeType/attributeType.js index 698d6ca3e9..4569a5f969 100644 --- a/packages/venia-ui/lib/components/ProductFullDetail/CustomAttributes/AttributeType/attributeType.js +++ b/packages/venia-ui/lib/components/ProductFullDetail/CustomAttributes/AttributeType/attributeType.js @@ -35,6 +35,12 @@ const defaultTypeConfig = { }, textarea: { component: Textarea + }, + texteditor: { + component: Textarea + }, + pagebuilder: { + component: Textarea } }; diff --git a/packages/venia-ui/lib/components/ProductFullDetail/CustomAttributes/__tests__/__snapshots__/customAttributes.spec.js.snap b/packages/venia-ui/lib/components/ProductFullDetail/CustomAttributes/__tests__/__snapshots__/customAttributes.spec.js.snap index 4248a85f01..cf95653915 100644 --- a/packages/venia-ui/lib/components/ProductFullDetail/CustomAttributes/__tests__/__snapshots__/customAttributes.spec.js.snap +++ b/packages/venia-ui/lib/components/ProductFullDetail/CustomAttributes/__tests__/__snapshots__/customAttributes.spec.js.snap @@ -2,9 +2,6 @@ exports[`#CustomAttributes renders with custom attributes visible on front only 1`] = `
-

- Details -

  • { - const { customAttributes } = props; + const { customAttributes, showLabels } = props; const classes = useStyle(defaultClasses, props.classes); const list = useMemo( @@ -26,7 +25,10 @@ const CustomAttributes = props => { key={currentAttribute.attribute_metadata.uid} className={classes.listItem} > - +
  • ); @@ -35,7 +37,7 @@ const CustomAttributes = props => { return previousAttribute; }, []), - [classes, customAttributes] + [classes, customAttributes, showLabels] ); if (list.length === 0) { @@ -44,12 +46,6 @@ const CustomAttributes = props => { return (
    -

    - -

      {list}
    ); diff --git a/packages/venia-ui/lib/components/ProductFullDetail/CustomAttributes/customAttributes.module.css b/packages/venia-ui/lib/components/ProductFullDetail/CustomAttributes/customAttributes.module.css index 97ab061828..7d1b530410 100644 --- a/packages/venia-ui/lib/components/ProductFullDetail/CustomAttributes/customAttributes.module.css +++ b/packages/venia-ui/lib/components/ProductFullDetail/CustomAttributes/customAttributes.module.css @@ -1,9 +1,4 @@ .root { - composes: mt-8 from global; -} - -.title { - composes: font-semibold from global; } .list { diff --git a/packages/venia-ui/lib/components/ProductFullDetail/__tests__/__snapshots__/productFullDetail.spec.js.snap b/packages/venia-ui/lib/components/ProductFullDetail/__tests__/__snapshots__/productFullDetail.spec.js.snap index b11d3f014c..32dd7ec31a 100644 --- a/packages/venia-ui/lib/components/ProductFullDetail/__tests__/__snapshots__/productFullDetail.spec.js.snap +++ b/packages/venia-ui/lib/components/ProductFullDetail/__tests__/__snapshots__/productFullDetail.spec.js.snap @@ -131,8 +131,8 @@ exports[`it disables the add to cart button when the talon indicates 1`] = ` className="descriptionTitle" > - - BTTF123 - @@ -261,8 +276,8 @@ exports[`it does not render options if the product is not a ConfigurableProduct className="descriptionTitle" > - - BTTF123 - @@ -425,8 +455,8 @@ exports[`it renders an error for an invalid cart 1`] = ` className="descriptionTitle" > - - BTTF123 - @@ -589,8 +634,8 @@ exports[`it renders an error for an invalid user token when adding to cart 1`] = className="descriptionTitle" > - - BTTF123 - @@ -754,8 +814,8 @@ Array [ className="descriptionTitle" > - - BTTF123 - , @@ -915,8 +990,8 @@ exports[`it renders correctly 1`] = ` className="descriptionTitle" > - - BTTF123 - @@ -1075,8 +1165,8 @@ exports[`it renders field level errors for quantity - message 1 1`] = ` className="descriptionTitle" > - - BTTF123 - @@ -1235,8 +1340,8 @@ exports[`it renders field level errors for quantity - message 2 1`] = ` className="descriptionTitle" > - - BTTF123 - @@ -1395,8 +1515,8 @@ exports[`it renders field level errors for quantity - message 3 1`] = ` className="descriptionTitle" > - - BTTF123 - @@ -1559,8 +1694,8 @@ exports[`it renders form level errors 1`] = ` className="descriptionTitle" > - - BTTF123 - @@ -1732,8 +1882,8 @@ exports[`it renders message with unsupported product type 1`] = ` className="descriptionTitle" > - - BTTF123 - @@ -1862,8 +2027,8 @@ exports[`out of stock disabled CTA button is rendered if out of stock 1`] = ` className="descriptionTitle" > - - BTTF123 - @@ -2024,8 +2204,8 @@ exports[`renders a WishlistButton with props 1`] = ` className="descriptionTitle" > - - BTTF123 - diff --git a/packages/venia-ui/lib/components/ProductFullDetail/productFullDetail.js b/packages/venia-ui/lib/components/ProductFullDetail/productFullDetail.js index e1b5f3f231..5caf37aae0 100644 --- a/packages/venia-ui/lib/components/ProductFullDetail/productFullDetail.js +++ b/packages/venia-ui/lib/components/ProductFullDetail/productFullDetail.js @@ -1,4 +1,4 @@ -import React, { Fragment, Suspense } from 'react'; +import React, { useMemo, Fragment, Suspense } from 'react'; import { FormattedMessage, useIntl } from 'react-intl'; import { arrayOf, bool, number, shape, string } from 'prop-types'; import { Form } from 'informed'; @@ -54,6 +54,7 @@ const ProductFullDetail = props => { customAttributes, wishlistButtonProps } = talonProps; + const { formatMessage } = useIntl(); const classes = useStyle(defaultClasses, props.classes); @@ -128,6 +129,44 @@ const ProductFullDetail = props => { } } + const customAttributesDetails = useMemo(() => { + const list = []; + const pagebuilder = []; + const skuAttribute = { + attribute_metadata: { + uid: 'attribute_sku', + used_in_components: ['PRODUCT_DETAILS_PAGE'], + ui_input: { + ui_input_type: 'TEXT' + }, + label: formatMessage({ + id: 'global.sku', + defaultMessage: 'SKU' + }) + }, + entered_attribute_value: { + value: productDetails.sku + } + }; + if (Array.isArray(customAttributes)) { + customAttributes.forEach(customAttribute => { + if ( + customAttribute.attribute_metadata.ui_input + .ui_input_type === 'PAGEBUILDER' + ) { + pagebuilder.push(customAttribute); + } else { + list.push(customAttribute); + } + }); + } + list.unshift(skuAttribute); + return { + list: list, + pagebuilder: pagebuilder + }; + }, [customAttributes, productDetails.sku, formatMessage]); + const cartCallToActionText = !isOutOfStock ? ( {
); + const shortDescription = productDetails.shortDescription ? ( + + ) : null; + + const pageBuilderAttributes = customAttributesDetails.pagebuilder.length ? ( +
+ +
+ ) : null; + return ( {breadcrumbs} @@ -187,6 +240,7 @@ const ProductFullDetail = props => { value={productDetails.price.value} />

+ {shortDescription}
@@ -226,22 +280,27 @@ const ProductFullDetail = props => { className={classes.descriptionTitle} >
- + - {productDetails.sku} - +
+ {pageBuilderAttributes}
); @@ -253,6 +312,8 @@ ProductFullDetail.propTypes = { description: string, descriptionTitle: string, details: string, + detailsPageBuilder: string, + detailsPageBuilderList: string, detailsTitle: string, imageCarousel: string, options: string, @@ -260,6 +321,7 @@ ProductFullDetail.propTypes = { productPrice: string, quantity: string, quantityTitle: string, + quantityRoot: string, root: string, title: string, unavailableContainer: string @@ -286,7 +348,11 @@ ProductFullDetail.propTypes = { file: string.isRequired }) ), - description: string + description: string, + short_description: shape({ + html: string, + __typename: string + }) }).isRequired }; diff --git a/packages/venia-ui/lib/components/ProductFullDetail/productFullDetail.module.css b/packages/venia-ui/lib/components/ProductFullDetail/productFullDetail.module.css index 10ebe79ce8..92065ea515 100644 --- a/packages/venia-ui/lib/components/ProductFullDetail/productFullDetail.module.css +++ b/packages/venia-ui/lib/components/ProductFullDetail/productFullDetail.module.css @@ -18,7 +18,7 @@ 'images quantity' 'images cart' 'images .'; - grid-template-columns: 1.5625fr 1fr; + grid-template-columns: minmax(0, 1.5625fr) minmax(0, 1fr); grid-template-rows: repeat(5, min-content) 1fr [fold]; } } @@ -140,6 +140,28 @@ composes: lg_self-stretch from global; } +.detailsPageBuilder { + composes: my-0 from global; + composes: mx-sm from global; + composes: px-0 from global; + composes: py-sm from global; + grid-column: 1 / span 2; +} + +.detailsPageBuilderList { + list-style: none; +} + +@media (min-width: 1024px) { + .details { + align-self: stretch; + border-top-width: 1px; + margin: 0; + padding-left: 1.5rem; + padding-right: 1.5rem; + } +} + .detailsTitle { composes: sectionTitle; } diff --git a/packages/venia-ui/lib/components/RichContent/plainHtmlRenderer.js b/packages/venia-ui/lib/components/RichContent/plainHtmlRenderer.js index 0e895f069a..7a628689b4 100644 --- a/packages/venia-ui/lib/components/RichContent/plainHtmlRenderer.js +++ b/packages/venia-ui/lib/components/RichContent/plainHtmlRenderer.js @@ -1,6 +1,7 @@ import React from 'react'; +import htmlStringImgUrlConverter from '@magento/peregrine/lib/util/htmlStringImgUrlConverter'; -const toHTML = str => ({ __html: str }); +const toHTML = str => ({ __html: htmlStringImgUrlConverter(str) }); function PlainHtmlRenderer({ html, classes }) { // Even if empty, render a div with no content, for styling purposes. diff --git a/packages/venia-ui/lib/targets/__tests__/venia-ui-targets.spec.js b/packages/venia-ui/lib/targets/__tests__/venia-ui-targets.spec.js index 966280382c..2b80a4f150 100644 --- a/packages/venia-ui/lib/targets/__tests__/venia-ui-targets.spec.js +++ b/packages/venia-ui/lib/targets/__tests__/venia-ui-targets.spec.js @@ -7,6 +7,7 @@ const { const { createTestInstance } = require('@magento/peregrine'); const declare = require('../venia-ui-declare'); const intercept = require('../venia-ui-intercept'); +const { DefinePlugin } = require('webpack'); const thisDep = { name: '@magento/venia-ui', @@ -59,7 +60,31 @@ test('uses RichContentRenderers to inject a default strategy into RichContent', const built = await buildModuleWith('../../components/RichContent', { context: __dirname, - dependencies: ['@magento/peregrine', thisDep] + dependencies: ['@magento/peregrine', thisDep], + plugins: [ + new DefinePlugin({ + STORE_VIEW_CODE: '"default"', + AVAILABLE_STORE_VIEWS: `[ + { + base_currency_code: 'USD', + code: 'default', + default_display_currency_code: 'USD', + id: 1, + locale: 'en_US', + store_name: 'Default Store View"' + }, + { + base_currency_code: 'EUR', + code: 'french', + default_display_currency_code: 'EUR', + id: 2, + locale: 'fr_FR', + secure_base_media_url: 'https://example.com/media/abcdef/', + store_name: 'French' + } + ]` + }) + ] }); const RichContent = built.run();