From 8013e2ee51e1814e518e0e9fda287ed1ae7f24e5 Mon Sep 17 00:00:00 2001 From: jstet Date: Fri, 25 Sep 2026 16:57:11 +0200 Subject: [PATCH] fix(lstsv2xlsform): reverse selected() on a multiple choice's native "other" #80 changed the select_multiple_other example to selected(${q}, 'other'), which the forward path writes as (q_other.NAOK == 'Y'): the native "other" is LimeSurvey's implicit `other` subquestion. The reverse didn't know that code, read q_other as a separate question and produced selected(${q_other}, 'Y'), failing the round-trip contract test. #80 merged with that test failing (my merge chain didn't check the CI exit status). The selected() lookup now includes the implicit `other` code for every multiple choice with other=Y, so the relevance reverses to selected(${q}, 'other') again. Co-Authored-By: Claude Opus 5.5 (1M context) --- src/pipelines/lstsv2xlsform/toXlsform.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/pipelines/lstsv2xlsform/toXlsform.ts b/src/pipelines/lstsv2xlsform/toXlsform.ts index 6535a4c..92c1ca4 100644 --- a/src/pipelines/lstsv2xlsform/toXlsform.ts +++ b/src/pipelines/lstsv2xlsform/toXlsform.ts @@ -433,9 +433,12 @@ function collectSelectMultiples( item.lsType === 'M' && !vocabFromCssClass(item.cssclass) ) { + const codes = choicesByName.get(item.name) ?? []; + // LimeSurvey's native "other" (other=Y) is the implicit `other` code, + // which the forward path references as `_other`. out.push({ name: item.name, - codes: choicesByName.get(item.name) ?? [], + codes: item.otherFlag ? [...codes, OTHER_CODE] : codes, }); } }