statt application/ld+json.
// Ein einfacher Regex reicht — wir brauchen nur das Flag, nicht die Daten.
const MICRODATA_RECIPE = /itemtype\s*=\s*["']https?:\/\/schema\.org\/Recipe["']/i;
export function hasRecipeMarkup(html: string): boolean {
if (MICRODATA_RECIPE.test(html)) return true;
try {
return findRecipeNode(html) !== null;
} catch {
return false;
}
}
// @deprecated use hasRecipeMarkup
export function hasRecipeJsonLd(html: string): boolean {
return hasRecipeMarkup(html);
}
function microdataValueOf(el: Element): string {
if (el.hasAttribute('content')) return (el.getAttribute('content') ?? '').trim();
const tag = el.tagName.toLowerCase();
if (tag === 'meta') return (el.getAttribute('content') ?? '').trim();
if (tag === 'a' || tag === 'link' || tag === 'area')
return (el.getAttribute('href') ?? '').trim();
if (
tag === 'img' ||
tag === 'source' ||
tag === 'video' ||
tag === 'audio' ||
tag === 'embed' ||
tag === 'iframe' ||
tag === 'track'
)
return (el.getAttribute('src') ?? '').trim();
if (tag === 'object') return (el.getAttribute('data') ?? '').trim();
if (tag === 'data' || tag === 'meter')
return (el.getAttribute('value') ?? '').trim();
if (tag === 'time')
return (el.getAttribute('datetime') ?? el.textContent ?? '').trim();
return (el.textContent ?? '').trim();
}
type MicroProps = Map
;
function gatherMicrodataProps(scope: Element): MicroProps {
// Alle itemprop-Descendants sammeln, dabei aber nicht in verschachtelte
// itemscopes einsteigen (sonst landen z.B. HowToStep.text im Haupt-Scope).
const map: MicroProps = new Map();
function walk(el: Element) {
for (const child of Array.from(el.children) as Element[]) {
const hasProp = child.hasAttribute('itemprop');
const hasScope = child.hasAttribute('itemscope');
if (hasProp) {
const names = (child.getAttribute('itemprop') ?? '')
.split(/\s+/)
.filter(Boolean);
for (const name of names) {
const arr = map.get(name) ?? [];
arr.push(child);
map.set(name, arr);
}
}
if (!hasScope) walk(child);
}
}
walk(scope);
return map;
}
function microText(map: MicroProps, name: string): string | null {
const els = map.get(name);
if (!els || els.length === 0) return null;
const v = microdataValueOf(els[0]);
return v || null;
}
function microAllTexts(map: MicroProps, name: string): string[] {
const els = map.get(name) ?? [];
return els.map(microdataValueOf).filter((v) => v !== '');
}
// Rausholen von Text mit erhaltenen Zeilenumbrüchen —
→ \n, Block-
// Elemente (,
…) bekommen ebenfalls Newline-Grenzen.
,