Skip to content

Commit

Permalink
feat(plugin-image): support breakpoints for sizes attribute generation
Browse files Browse the repository at this point in the history
Signed-off-by: Chawye Hsu <[email protected]>
  • Loading branch information
chawyehsu committed Jan 21, 2025
1 parent 07cbbd5 commit 57af993
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 15 deletions.
77 changes: 64 additions & 13 deletions packages/saber-plugin-image/components/SaberImage.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,70 @@
export default {
name: 'SaberImage',
props: ['src'],
render(h) {
const { $attrs } = this
/**
* @param {import('vue').h} h
* @param {*} ctx
* @param {Array<number>} breakpoints
* @returns {import('vue').VNode} the image element
*/
function renderer(h, ctx, breakpoints = []) {
const { $attrs } = ctx

if (typeof this.src === 'string') {
return h('img', {
attrs: { ...$attrs, src: this.src },
})
if (typeof ctx.src === 'string') {
return h('img', {
attrs: { ...$attrs, src: ctx.src },
})
}

const { width, height, src, images, srcSet: srcset } = ctx.src || {}
const imagesLength = images.length
const bpLength = breakpoints.length

const sizes = []
if (imagesLength && bpLength) {
if (bpLength >= imagesLength) {
for (let idx = 0; idx < bpLength; idx++) {
const imgExceeded = idx >= imagesLength
if (imgExceeded) {
break
}
const bp = breakpoints[idx]
sizes.push(`(max-width: ${bp}px) ${images[idx].width}px`)
}
} else {
for (let idx = 0; idx < imagesLength; idx++) {
const bpLast = idx === bpLength
const bpExceeded = idx > bpLength
if (bpExceeded) {
break
}
sizes.push(bpLast ? `${images[idx].width}px` : `(max-width: ${breakpoints[idx]}px) ${images[idx].width}px`)
}
}
}

const { width, height, src, srcSet: srcset } = this.src || {}
const attrs = { ...$attrs, src, srcset, width, height }
if (sizes.length) {
attrs.sizes = sizes.join(',')
}

return h('img', {
attrs: { ...$attrs, src, srcset, width, height },
})
return h('img', { attrs })
}

/**
* @param {Array<number> | undefined} breakpoints
*/
export function withBreakpoints(breakpoints) {
return {
name: 'SaberImage',
props: ['src'],
render(h) {
return renderer(h, this, breakpoints)
},
}
}

export default {
name: 'SaberImage',
props: ['src'],
render(h) {
renderer(h, this)
},
}
3 changes: 3 additions & 0 deletions packages/saber-plugin-image/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ function detectAdapter(adapter) {
}
}

/**
* @param {import('@alterjs/saber').Saber} api
*/
exports.apply = (api, options = {}) => {
options = Object.assign(
{
Expand Down
7 changes: 5 additions & 2 deletions packages/saber-plugin-image/saber-browser.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import SaberImage from './components/SaberImage'
import { withBreakpoints } from './components/SaberImage'

export default ({ Vue }) => {
Vue.component(SaberImage.name, SaberImage)
// eslint-disable-next-line no-undef
const options = __SABER_IMAGE_OPTIONS__
const component = withBreakpoints(options.breakpoints)
Vue.component(component.name, component)
}

0 comments on commit 57af993

Please sign in to comment.