diff --git a/services/graphql-server/src/graphql/definitions/platform/content/index.js b/services/graphql-server/src/graphql/definitions/platform/content/index.js index 0d738a53f..3c2dc87bf 100644 --- a/services/graphql-server/src/graphql/definitions/platform/content/index.js +++ b/services/graphql-server/src/graphql/definitions/platform/content/index.js @@ -175,7 +175,7 @@ enum RelatedContentQueryType { } type ContentStubSidebar { - body: String + body(input: ContentStubSidebarBodyInput = {}): String name: String label: String sequence: Int! @@ -304,6 +304,15 @@ type QueryMostPopularContentEdge { node: MostPopularContent! } +input ContentStubSidebarBodyInput { + "Embedded image defaults to apply to inline images" + imageAttrs: EmbeddedImageAttrsInput = { + w: 1280, + fit: "max", + auto: "format,compress" + } +} + input ContentQueryInput { siteId: ObjectID status: ModelStatus = active @@ -665,6 +674,20 @@ input ContentTeaserInput { input ContentBodyInput { mutation: ContentMutation = Website + imageAttrs: EmbeddedImageAttrsInput = { + w: 1280, + fit: "max", + auto: "format,compress" + } +} + +input EmbeddedImageAttrsInput { + "The width of the embedded image" + w: Int + "The Imgix 'fit' parameter" + fit: String + "The Imgix 'auto' parameter" + auto: String } input ContentTaxonomyInput { diff --git a/services/graphql-server/src/graphql/resolvers/platform/content.js b/services/graphql-server/src/graphql/resolvers/platform/content.js index 1a9a2f82c..48e12caef 100644 --- a/services/graphql-server/src/graphql/resolvers/platform/content.js +++ b/services/graphql-server/src/graphql/resolvers/platform/content.js @@ -192,12 +192,12 @@ const updateContentMutationHandler = ({ return basedb.findById('platform.Content', id, { projection: { ...projection, type: 1 } }); }; -const prepareSidebarBody = async (body, { site, basedb }) => { +const prepareSidebarBody = async (body, { site, imageAttrs, basedb }) => { if (!body) return null; let value = body.trim(); if (!value) return null; const imageHost = site.get('imageHost', defaults.imageHost); - const imageTags = await getEmbeddedImageTags(value, { imageHost, basedb }); + const imageTags = await getEmbeddedImageTags(value, { imageHost, imageAttrs, basedb }); imageTags.forEach((tag) => { const replacement = tag.isValid() ? tag.build() : ''; value = value.replace(tag.getRegExp(), replacement); @@ -472,7 +472,7 @@ module.exports = { taxonomyIds: content => getAsArray(content, 'taxonomy').map(t => parseInt(t.oid, 10)).filter(id => id), body: async (content, { input }, { site, basedb }) => { - const { mutation } = input; + const { mutation, imageAttrs } = input; const { body } = content; const mutated = get(content, `mutations.${mutation}.body`); @@ -482,7 +482,7 @@ module.exports = { // Convert image tags to include image attributes (src, alt, caption, credit). // Convert document tags to include href and file extension. const [imageTags, documentTags] = await Promise.all([ - getEmbeddedImageTags(value, { imageHost, basedb }), + getEmbeddedImageTags(value, { imageHost, imageAttrs, basedb }), getEmbeddedDocumentTags(value, { imageHost, basedb }), ]); @@ -648,10 +648,10 @@ module.exports = { * */ ContentArticle: { - sidebars: async ({ sidebars }, _, { site, basedb }) => { + sidebars: async ({ sidebars }, { imageAttrs }, { site, basedb }) => { if (!isArray(sidebars)) return []; const bodies = await Promise.all(sidebars.map(async ({ body } = {}) => { - const value = await prepareSidebarBody(body, { site, basedb }); + const value = await prepareSidebarBody(body, { site, imageAttrs, basedb }); return value; })); return bodies.filter(v => v); @@ -785,8 +785,9 @@ module.exports = { }, ContentStubSidebar: { - body: async ({ body }, _, { site, basedb }) => { - const value = await prepareSidebarBody(body, { site, basedb }); + body: async ({ body }, { input }, { site, basedb }) => { + const { imageAttrs } = input; + const value = await prepareSidebarBody(body, { site, imageAttrs, basedb }); return value; }, name: ({ name }) => { diff --git a/services/graphql-server/src/graphql/utils/embedded-image-tags.js b/services/graphql-server/src/graphql/utils/embedded-image-tags.js index 0d4abedab..d3f086099 100644 --- a/services/graphql-server/src/graphql/utils/embedded-image-tags.js +++ b/services/graphql-server/src/graphql/utils/embedded-image-tags.js @@ -1,7 +1,13 @@ const { extractEmbeddedTags } = require('@parameter1/base-cms-embedded-media'); const { createAltFor, createSrcFor, createCaptionFor } = require('@parameter1/base-cms-image'); -module.exports = async (body, { imageHost, basedb }) => { +const defaults = { + w: '1280', + fit: 'max', + auto: 'format,compress', +}; + +module.exports = async (body, { imageHost, imageAttrs, basedb }) => { if (!body) return []; const imageTags = extractEmbeddedTags(body).filter(tag => tag.type === 'image'); return Promise.all(imageTags.map(async (tag) => { @@ -20,16 +26,11 @@ module.exports = async (body, { imageHost, basedb }) => { tag.setValid(false); return tag; } - // const defaultSize = ['left', 'right'].includes(tag.get('align')) ? '320' : '640'; - // const size = tag.get('size', defaultSize).replace('w', ''); - // @todo Adjust this. Hardcoding for now to allow for crisp images until proper w/h is handled. - const size = '1440'; tag.set('alt', createAltFor(image)); tag.set('src', createSrcFor(imageHost, image, { - w: size, - fit: 'max', - auto: 'format', + ...defaults, + ...imageAttrs, })); tag.set('caption', createCaptionFor(image.caption)); tag.set('credit', image.credit);