@@ -1325,14 +1325,14 @@ impl Parser {
13251325 let var_name = var_names[0].clone();
13261326 let index_var = var_names.get(1).cloned();
13271327
1328− // Strip a trailing `[page N]` pagination suffix so it doesn't end
1329− // up in the last item; it's parsed from the raw line below.
1330− let list_str = match list_str.rfind("[page ") {
1331− Some(pos) if list_str.trim_end().ends_with(']') => {
1332− list_str[..pos].trim_end().to_string()
1333− }
1334− _ => list_str,
1335− };
1328+ if list_str.trim_end().ends_with(']') && list_str.contains("[page ") {
1329+ return Err(ParseError {
1330+ line: line_num,
1331+ message: "@each pagination (`[page N]`) was removed: split the list or \
1332+ filter it with @if"
1333+ .to_string(),
1334+ });
1335+ }
13361336 track_var_refs(&list_str, &mut ctx.used_variables);
13371337 let list_str = substitute_vars(&list_str, &ctx.variables);
13381338 // Support range syntax: @each $i in 1..5 or @each $i in 0..100 step 10
@@ -1360,50 +1360,6 @@ impl Parser {
13601360 .collect()
13611361 };
13621362
1363− // Pagination: check for [page N] or [page N per P] suffix
1364− // Parse from the original rest before substitution
1365− let (items, pagination_info) = {
1366− // Check if list_str ended with a page directive (already consumed in items)
1367− // Instead, check the raw rest for [page ...] syntax
1368− let raw_rest = rest;
1369− let page_size = if let Some(page_pos) = raw_rest.find("[page ") {
1370− let after = &raw_rest[page_pos + 6..];
1371− if let Some(close) = after.find(']') {
1372− let page_spec = after[..close].trim();
1373− page_spec.parse::<usize>().ok()
1374− } else {
1375− None
1376− }
1377− } else {
1378− None
1379− };
1380−
1381− if let Some(size) = page_size {
1382− let current_page: usize = ctx
1383− .variables
1384− .get("_page")
1385− .and_then(|v| v.parse().ok())
1386− .unwrap_or(1)
1387− .max(1);
1388− let size = size.max(1);
1389− let total_items = items.len();
1390− let total_pages = total_items.div_ceil(size);
1391− let start = (current_page - 1).saturating_mul(size);
1392− let end = start.saturating_add(size).min(total_items);
1393− let page_items: Vec<String> = if start < total_items {
1394− items[start..end].to_vec()
1395− } else {
1396− Vec::new()
1397− };
1398− (
1399− page_items,
1400− Some((current_page, total_pages, size, total_items)),
1401− )
1402− } else {
1403− (items, None)
1404− }
1405− };
1406−
14071363 // Collect body lines
14081364 let mut body_lines = Vec::new();
14091365 while self.pos < self.lines.len() && self.lines[self.pos].indent > current_indent {
@@ -1466,17 +1422,6 @@ impl Parser {
14661422 let saved_vars = ctx.variables.clone();
14671423 let mut all_nodes = Vec::new();
14681424
1469− // Inject pagination variables if pagination is active
1470− if let Some((page, total_pages, page_size, total_items)) = pagination_info {
1471− ctx.variables.insert("_page".to_string(), page.to_string());
1472− ctx.variables
1473− .insert("_total_pages".to_string(), total_pages.to_string());
1474− ctx.variables
1475− .insert("_page_size".to_string(), page_size.to_string());
1476− ctx.variables
1477− .insert("_total_items".to_string(), total_items.to_string());
1478− }
1479−
14801425 let has_extra_vars = var_names.len() > 2
14811426 || (var_names.len() == 2 && items.first().is_some_and(|it| it.contains(' ')));
14821427