Shallie/src/lib/content/postProcessor.ts

70 lines
2.2 KiB
TypeScript

import { unified } from "unified";
import type { Plugin } from "unified";
import parse from "rehype-parse";
import stringify from "rehype-stringify";
import { visit } from 'unist-util-visit'
import { fromSelector } from 'hast-util-from-selector';
import { generateSizesString, generateSrcsetString } from "./srcset";
const sizes = [300, 600, 1000, 1500, 2000];
const embedSrcs = [
/'*player.vimeo.com.*/,
/.*youtube.com.*/,
/.*youtube-nocookie.com.*/,
/.*kickstarter.com.*video.html.*/,
];
const processEmbed = (parent: any, node: any) => {
const wrapper = fromSelector('div');
wrapper.children = [node];
const width = node.properties.width;
const height = node.properties.height;
const aspect = height / width;
wrapper.properties = {
class: ['fluid-width-video-wrapper'],
style: `padding-top: ${aspect * 100}%`
};
node.properties.height = null;
node.properties.width = null;
parent.children = parent.children.filter((x: any) => x != node);
parent.children.unshift(wrapper);
}
export const postProcessor: Plugin = () => {
return (tree) => {
visit(tree, 'element', (node: any, i: number, parent: any) => {
// Responsive
if (node.tagName == 'img') {
const src = node.properties.src;
const srcsetString = generateSrcsetString(src);
const sizesString = generateSizesString();
node.properties.srcset = srcsetString;
node.properties.sizes = `${sizesString}`;
}
// Embeds
if (node.tagName == 'iframe') {
embedSrcs.forEach(x => {
if (node.properties.src.match(x)) {
processEmbed(parent, node);
}
});
}
if (node.tagName == 'object' || node.tagName == 'embed') {
processEmbed(parent, node);
}
})
}
}
export const processPostHtml = async (postHtml: string) => {
const processor = unified()
.use(parse)
.use(postProcessor)
.use(stringify);
const result = await processor.process(postHtml);
return result.toString();
}