Especially when you generating images from
- Hotlinking (which probably you shouldn't do)
- Pasting from clipboard
This is an example of such pasting function,
// @ts-ignore | |
import { getMetadata } from 'page-metadata-parser' | |
import he from 'he' | |
export function addImagedLinksToTextAreaOnPaste(el: HTMLTextAreaElement) { | |
const pasteEvent = async (ev: ClipboardEvent) => { | |
const { items } = ev.clipboardData || {} | |
if (items) { | |
for (const k of Object.keys(items)) { | |
const item = (items as any)[k] as DataTransferItem | |
if (item.type === 'text/plain') { | |
ev.preventDefault() | |
const { selectionStart } = el | |
item.getAsString(async (str) => { | |
if (isUrl(str)) { | |
const rawHtml = await fetch( | |
`https://cors-anywhere.herokuapp.com/${str}` | |
).then((r) => r.text()) | |
const div = document.createElement('div') | |
div.innerHTML = rawHtml | |
const meta = getMetadata(div, str) | |
div.remove() | |
const imgPos = meta.imgPos || 'left' | |
const img = ` | |
<img style="${ | |
imgPos === 'left' | |
? 'max-width: 200px; margin-right: 1em; width: 100%; height: auto;' | |
: 'margin-bottom: 1em; width: 100%; height: auto;' | |
}" ${ | |
meta | |
? meta.image | |
? `src="${encodeURI(meta.image)}" ` + | |
`alt="${he.encode(meta.title || meta.url)}" ` | |
: '' | |
: '' | |
} />` | |
const innerHTML = `${ | |
meta.image | |
? ` | |
<div style="${(imgPos === 'left' | |
? 'max-width: 200px; margin-right: 1em;' | |
: '') + | |
'display: flex; align-items: center; justify-content: center;' + | |
'overflow: hidden;'}">${img} | |
</div>` | |
: '' | |
} | |
<div> | |
${ | |
meta.title | |
? `<h3 style="color: darkblue; margin-block-start: 0;">${he.encode( | |
meta.title | |
)}</h3>` | |
: `<h6 style="color: darkblue; margin-block-start: 0;">${he.encode( | |
meta.url | |
)}</h6>` | |
} | |
${he.encode(meta.description || '')} | |
</div>` | |
const imagedLinkHtml = ` | |
<a is="a-card" style="${`flex-direction: ${ | |
imgPos === 'left' ? 'row' : 'column' | |
};` + | |
'display: flex;' + | |
'margin: 1em; padding: 1em;' + | |
'box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);'}" href="${encodeURI( | |
meta.url | |
)}" | |
rel="noopener" target="_blank"> | |
${innerHTML} | |
</a>` | |
const { value } = el | |
el.value = | |
value.substring(0, selectionStart) + | |
'\n' + | |
imagedLinkHtml + | |
'\n' + | |
value.substring(selectionStart) | |
} | |
}) | |
} else if (item.kind === 'file') { | |
const blob = item.getAsFile()! | |
ev.preventDefault() | |
const { selectionStart } = el | |
const reader = new FileReader() | |
reader.onload = function() { | |
const dataUrl = reader.result | |
const imageId = Math.random().toString(36).substring(2) | |
const { value } = el | |
el.value = | |
value.substring(0, selectionStart) + | |
`![clipboard ${new Date().toDateString()}][${imageId}]` + | |
value.substring(selectionStart) + | |
'\n' + | |
`[${imageId}]: ${dataUrl}` | |
} | |
reader.readAsDataURL(blob); | |
} | |
} | |
} | |
el.addEventListener('paste', pasteEvent) | |
return () => { | |
el.removeEventListener('paste', pasteEvent) | |
} | |
} | |
function isUrl(s: string) { | |
if (/^https?:\/\/[^ ]+$/.test(s)) { | |
try { | |
// eslint-disable-next-line no-new | |
new URL(s) | |
return true | |
} catch (_) {} | |
} | |
return false | |
} |
So, what do you recommend I do?
- Proxy with Cloudinary?
- Make my own proxy server?
- Save image locally, then parse to multiple sizes (probably with sharp)?
- Are there some guidelines on how to do this?
- Or, just use a headless CMS?
Top comments (4)
ImageKit.io
At a first glance, how different is it from Cloudinary?
Also Cloudinary seems to provide Components for popular frameworks as well, such as cloudinary-vue.
ImageKit has unlimited requests an transformations (but weird limited storage). See imagekit.io/plans. Pair it with S3 or B2 maybe?
Else you have statically.io I found recently on dev.to which is mostly a free CDN maintained by Frans Ellen (he's a dev.to user). I forgot to asked him about privacy concerns though...
As for components integration, I think you can handle it yourself.