fix: fixed title parsing for special characters

This commit is contained in:
Leyla Becker 2026-02-22 17:05:57 -06:00
parent 602e92f986
commit 93837aaf20
2 changed files with 70 additions and 38 deletions

View file

@ -371,21 +371,83 @@ function findDimensions(text) {
/**
* Find weight measurements in text.
*
* Handles: 200g, 550 g, ~250g, 180-240g, 1kg, 227g (8 oz)
* Handles: 200g, 550 g, ~250g, 180-240g, 1kg, 227g (8 oz),
* 80g (1/3 cups), 860g (800mL (3 1/3 cups))
*/
function findWeights(text) {
const results = [];
// Supports optional nested alternatives:
// 860g (800mL (3 1/3 cups)) → primary=860g, outer=800mL, inner=3 1/3 cups
// 80g (1/3 cups) → primary=80g, outer=1/3 cups
// 227g (8 oz) → primary=227g, outer=8 oz
const weightRe = new RegExp(
`(${AMOUNT})\\s*(${WEIGHT_UNIT})\\b` +
`(?:\\s*\\(\\s*(${AMOUNT})\\s*(${WEIGHT_UNIT}|${VOLUME_UNIT})\\s*\\))?`,
`(?:\\s*\\(\\s*(${AMOUNT})\\s*(${WEIGHT_UNIT}|${VOLUME_UNIT})\\b` +
`(?:\\s*\\(\\s*(${AMOUNT})\\s*(${WEIGHT_UNIT}|${VOLUME_UNIT})\\s*\\))?` +
`\\s*\\))?`,
'gi'
);
let m;
while ((m = weightRe.exec(text)) !== null) {
// Avoid matching dimension patterns (e.g., the "g" in "9x13 glass")
// Check if this match overlaps with any dimension
const amount = parseAmount(m[1]);
const unit = normalizeUnit(m[2]);
let alt = null;
let intermediate = null;
if (m[5] && m[6]) {
// Nested alt: e.g. 860g (800mL (3 1/3 cups))
// Inner alt is the display alternative, outer is the intermediate for scaling
alt = {
amount: parseAmount(m[5]),
unit: normalizeUnit(m[6]),
};
intermediate = {
amount: parseAmount(m[3]),
unit: normalizeUnit(m[4]),
};
} else if (m[3] && m[4]) {
// Simple alt: e.g. 227g (8 oz), 80g (1/3 cups)
alt = {
amount: parseAmount(m[3]),
unit: normalizeUnit(m[4]),
};
}
results.push({
match: m[0],
index: m.index,
type: 'weight',
amount,
unit,
approximate: typeof amount.approximate === 'boolean' ? amount.approximate : false,
alt,
intermediate,
});
}
return results;
}
/**
* Find volume measurements in text.
*
* Handles: 2 quarts, 1/2 cups, 1 cup, 6 tablespoons, 6 table spoons,
* 1 1/2 tablespoon, 3/4 teaspoon, 6 parts by volume,
* 800mL (3 1/3 cups)
*/
function findVolumes(text) {
const results = [];
const volumeRe = new RegExp(
`(${AMOUNT})\\s*(${VOLUME_UNIT})\\b` +
`(?:\\s*\\(\\s*(${AMOUNT})\\s*(${VOLUME_UNIT}|${WEIGHT_UNIT})\\s*\\))?`,
'gi'
);
let m;
while ((m = volumeRe.exec(text)) !== null) {
const amount = parseAmount(m[1]);
const unit = normalizeUnit(m[2]);
let alt = null;
@ -395,38 +457,6 @@ function findWeights(text) {
unit: normalizeUnit(m[4]),
};
}
results.push({
match: m[0],
index: m.index,
type: 'weight',
amount,
unit,
approximate: typeof amount.approximate === 'boolean' ? amount.approximate : false,
alt,
});
}
return results;
}
/**
* Find volume measurements in text.
*
* Handles: 2 quarts, 1/2 cups, 1 cup, 6 tablespoons, 6 table spoons,
* 1 1/2 tablespoon, 3/4 teaspoon, 6 parts by volume
*/
function findVolumes(text) {
const results = [];
const volumeRe = new RegExp(
`(${AMOUNT})\\s*(${VOLUME_UNIT})\\b`,
'gi'
);
let m;
while ((m = volumeRe.exec(text)) !== null) {
const amount = parseAmount(m[1]);
const unit = normalizeUnit(m[2]);
results.push({
match: m[0],
index: m.index,
@ -434,7 +464,7 @@ function findVolumes(text) {
amount,
unit,
approximate: typeof amount.approximate === 'boolean' ? amount.approximate : false,
alt: null,
alt,
});
}

View file

@ -44,6 +44,8 @@ const getPlantBased = (filePath) => {
const slugify = (text) => {
return text
.toLowerCase()
.normalize('NFD') // Decompose accented characters
.replace(/[\u0300-\u036f]/g, '') // Remove combining diacritical marks
.replace(/\s+/g, '-') // Replace spaces with hyphens
.replace(/[()]/g, '') // Remove parentheses
.replace(/[^\w-]+/g, '') // Remove non-word chars except hyphens
@ -224,7 +226,7 @@ module.exports = {
return getSlugFromPath(data.page.inputPath);
},
title: (data) => {
if (data.title && data.title !== data.page.fileSlug) {
if (data.title) {
return data.title;
}
const slug = getSlugFromPath(data.page.inputPath);