Skip to content

Instantly share code, notes, and snippets.

@stevekinney
Created March 22, 2024 01:10
Show Gist options
  • Save stevekinney/dcafe87337efd9c14dddea3d3080e980 to your computer and use it in GitHub Desktop.
Save stevekinney/dcafe87337efd9c14dddea3d3080e980 to your computer and use it in GitHub Desktop.
export const processImages = () => {
return {
name: 'markdown-image-optimization',
/**
* @param {object} options
* @param {string} options.content
* @param {string} options.filename
*/
markup: ({ content, filename }) => {
if (!filename.endsWith('.md')) return;
const { instance, html } = parse(content);
const s = new MagicString(content);
/** @type {Map<string, { url: string, id: string }>} */
const images = new Map();
/** @param {BaseNode} node
* @returns {node is ElementNode}
*/
const isElement = (node) => node.type === 'Element';
walk(html, {
enter(node) {
if (isElement(node) && node.name === 'img') {
const src = node.attributes.find((attr) => attr.name === 'src');
if (!src) return;
const [srcValue] = src.value;
const url = decodeURIComponent(srcValue.data);
const id = '_' + camelCase(url);
images.set(url, { id, url });
s.update(srcValue.start, srcValue.end, `{${id}}`);
const classes = [
'max-w-full',
'rounded-md',
'shadow-md',
'border-2',
'border-slate-300',
];
const classAttr = node.attributes.find((attr) => attr.name === 'class');
if (classAttr) {
const [classValue] = classAttr.value;
s.update(classValue.start, classValue.end, merge(classValue.data, classes));
} else {
s.appendLeft(node.start + 4, ` class="${classes.join(' ')}"`);
}
}
},
});
if (instance) {
walk(instance, {
enter(node) {
if (node.type === 'Program') {
const imports = Array.from(images.entries())
.map(([url, { id }]) => {
const location = url.endsWith('.gif') ? url : `${url}?w=768`;
return `import ${id} from '${location}';`;
})
.join('\n');
s.appendLeft(node.end, imports);
}
},
});
}
return {
code: s.toString(),
map: s.generateMap({ hires: true }),
};
},
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment