You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
50 lines
1.4 KiB
50 lines
1.4 KiB
import { isImageUrl } from '@/lib/image-extraction' |
|
|
|
export const POLL_OPTION_IMAGE_MAX_HEIGHT_PX = 200 |
|
|
|
export type TPollOptionImagePart = { url: string; alt: string } |
|
|
|
/** |
|
* Split a poll `option` tag label into plain text and image URLs (markdown `` or bare https image links). |
|
*/ |
|
export type TPollOptionVisualParts = { |
|
text: string |
|
images: TPollOptionImagePart[] |
|
} |
|
|
|
export function parsePollOptionVisualParts(label: string): TPollOptionVisualParts { |
|
const images: TPollOptionImagePart[] = [] |
|
const seen = new Set<string>() |
|
|
|
const push = (url: string, alt: string) => { |
|
const u = url.trim() |
|
if (!u || seen.has(u)) return |
|
seen.add(u) |
|
images.push({ url: u, alt: alt.trim() }) |
|
} |
|
|
|
let rest = label |
|
const mdRe = /!\[([^\]]*)\]\(([^)]+)\)/g |
|
let m: RegExpExecArray | null |
|
while ((m = mdRe.exec(label)) !== null) { |
|
push(m[2] ?? '', m[1] ?? '') |
|
} |
|
rest = rest.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, ' ').replace(/\s+/g, ' ').trim() |
|
|
|
if (images.length === 0 && rest) { |
|
const single = rest.trim() |
|
if (!/\s/.test(single) && /^https?:\/\//i.test(single) && isImageUrl(single)) { |
|
return { text: '', images: [{ url: single, alt: '' }] } |
|
} |
|
} |
|
|
|
const tokens = rest.match(/https?:\/\/[^\s]+/gi) || [] |
|
for (const t of tokens) { |
|
if (seen.has(t) || !isImageUrl(t)) continue |
|
push(t, '') |
|
rest = rest.split(t).join(' ') |
|
} |
|
|
|
rest = rest.replace(/\s+/g, ' ').trim() |
|
return { text: rest, images } |
|
}
|
|
|