Skip to content

Instantly share code, notes, and snippets.

@kmelve
Created January 11, 2018 14:37
Show Gist options
  • Select an option

  • Save kmelve/a4966ea8b1c507b41bae12241efa77f8 to your computer and use it in GitHub Desktop.

Select an option

Save kmelve/a4966ea8b1c507b41bae12241efa77f8 to your computer and use it in GitHub Desktop.
Sanity BlockContent in Vue
<style lang="scss">
a.button {
text-decoration: none;
display: inline-block;
}
.blurb, .quote > * {
padding-bottom: 1rem;
@media(min-width: 800px) {
padding-bottom: 0;
}
}
</style>
<template>
<div v-html="renderHtml(content)"></div>
</template>
<script>
/* eslint-disable */
const blocksToHtml = require('@sanity/block-content-to-html');
const h = require('hyperscript')
import imageUrlBuilder from '@sanity/image-url'
import client from '@/services/sanity'
const builder = imageUrlBuilder(client)
const urlFor = source => builder.image(source)
const urlResolver = (link = '') => {
if (link.hasOwnProperty('current')) {
return `/${link.current}`
}
if (link.hasOwnProperty('link')) {
return `/${link.link.current}`
}
else if (link.hasOwnProperty('external'))
{
return link.external
}
}
const serializers = {
marks: {
link: ({ mark: { href = '' } = {}, children = [] }) => h('a', {className: 'link', href, innerHTML: children } ),
},
types: {
accordion: ({ heading = '', items = [] }) => (
h('div', { className: 'block --bg-alt --pb-largest --pt-largest' },
h('div', { className: 'container --narrow' }),
h('div', { className: 'block --full --pb --text-center'},
h('h2', heading)
),
h('div', { className: 'block --full' },
h('div', { className: 'accordion' },
items.map(({ heading = '', content = []})=> h('details', { className: 'accordion__item' },
h('summary', { className: 'accordion__item-button' }, heading),
h('div', { className: 'accordion__item-content', innerHTML: blocksToHtml({ blocks: content, serializers })})
)
)
)
)
)
),
textWithImage: ({ node: { index, heading = '', avsnitt = [], image = {} }}) => (
h('div', { className: 'block --bg-alt --pb-largest --pt-largest' },
h('div', { className: 'container --wide' },
h('div', { className: "grid --middle --space-between", style: { 'flex-direction' : (image && index % 2) ? 'row-reverse' : 'row '}},
h('div', { className: "grid__item --s-7 --m-4" },
heading && h('h3', heading),
avsnitt && h('div', { innerHTML: blocksToHtml({ blocks: avsnitt, serializers })})
),
h('div', { className: 'grid__item --s-4 --m-6' },
image ? h('img', { className: 'img', src: urlFor(image).url() }) : ''
)
)
)
)
),
richText: props => h('div', { className: 'block --pt-largest --pb-largest'},
h('div', { className: 'container --narrow' }, { innerHTML: blocksToHtml({ blocks: props.node.content, serializers })})
),
citation: ({ node: { citation, person }}) => h('div', { className: 'block --pb-largest --pt-larger'},
h('div', { className: 'container'},
h('div', { className: 'block --full --pb-large'},
h('blockquote', { className: 'quote'},
person && h('div', { className: 'quote__person'},
h('img', { className: 'quote__img', src: person.image ? urlFor(person.image).width(200).height(200).url() : 'http://thesteppingstonesgroup.com/wp-content/uploads/2016/02/ingrid-gimenez.jpg'}),
person.firstName && h('div', { className: 'quote__name'}, h('span', {}, `${person.firstName} ${person.lastName ? person.lastName : ''}`)),
person.position && h('div', { className: 'quote__position'}, person.position)
),
citation && h('div', { className: 'quote__messsage'}, citation)
)
)
)
),
callToAction: ({ node: { text, link = false } }) => {
return (
text &&
link &&
h(
'div',
{ className: 'block --text-center --pb-largest --pt-largest' },
h(
'div',
{ className: 'container --wide' },
h('a', { className: 'button --primary', href: urlResolver(link) }, text)
)
)
);
/*
* Vi skal "egentlig" ha denne her:
* <router-link to="/bestill" tag="button" class="button --primary">Prøv gratis i 30 dager</router-link>
* */
},
proposition: ({ node: { heading = '', feature = [], callToAction = {} } = {} }) => (
h('div', { className: 'block --pt-largest --pb-largest' },
h('div', { className: 'container --wide' },
h('div', { className: 'block --pb-largest --text-center'},
h('h2', heading)
),
h('div', { className: 'grid --space-around --text-center' },
feature.map(({ image = false, heading: subHeading = '', description = '' }) => h('div', { className: 'grid__item --s-8 --m-3' },
h('div', { className: 'blurb' },
image ? h('img', { className: 'blurb__img', src: urlFor(image).url() }) : '',
subHeading.length > 0 ? subHeading && h('h3', subHeading) : '',
description && h('p', description)
))
)
),
h('div', { className: 'block --pt-largest --text-center' },
callToAction.text && h('a', { href: urlResolver(callToAction), className: "button --small --primary --outline" }, callToAction.text)
)
)
)
),
listEntries: (props) => console.log(props)
}
};
export default {
name: 'BlockToHtml',
props: ['content'],
methods: {
renderHtml(item) {
return blocksToHtml({
/**
* Add index to textWithImage in order to make alternating
* flex directions possible
*/
blocks: item.map((i, index) => i._type === 'textWithImage' ? { index, ...i } : i),
serializers: serializers
});
}
}
};
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment