Собственно кусок кода проекта из нашей статьи)
https://habr.com/post/414137/<script>
import {parse} from 'himalaya'
import Product from '~/components/Product/Product.vue';
const hasProduct = parsedHtml => {
let has = false;
if (parsedHtml.children) {
parsedHtml.children.forEach(ch => {
if(has) return;
if (ch.tagName == 'product') {
has = true;
} else {
has = hasProduct(ch);
}
});
}
return has;
};
const toElement = (h, products) => parsedHtml => {
if (parsedHtml.type == 'Text') {
return [h('span', {
domProps: {
innerHTML: parsedHtml.content
},
})];
}
if (parsedHtml.tagName == 'product') {
let product = products.find(product => product.slug == parsedHtml.attributes.slug);
if (!product) return '';
return [h('div', {
'class': ['catalog', 'catalog_view_row'],
}, [
h('div', {
'class': ['catalog__cell'],
}, [
h(
'product',
{props: {product}}
)
])
])];
}
let has = hasProduct(parsedHtml);
return h(
has ? 'div' : parsedHtml.tagName,
{
'class': parsedHtml.attributes.className,
'attrs': parsedHtml.attributes,
},
parsedHtml.children
? parsedHtml.children.map(toElement(h, products))
: []
)
};
export default {
components: {
Product,
},
props: [
'html',
'products',
],
render(h) {
let tree = parse(`<div>${this.html}</div>`);
return tree.map(toElement(h, this.products))[0];
}
};
</script>
И регулярга:
let match = article.content.match(/\$product\[([^\]]+)\]/g);
if(match != null && match.length) {
let promises = match.map(async (m) => {
let slug = m.match(/\[(.+)\]/)[1];
try {
let product = await ctx.app.$api.product(slug);
if(product) products.push(product);
} catch (e) {
}
});
await Promise.all(promises);
}