Skip to main content
Fixes collapsed speaker lines by inserting newlines before mid-line speaker labels. This corrects a common LLM error where dialogue turns are merged onto one line instead of being separated.

Function Signature

fixCollapsedSpeakerLines(text: string, config?: FixConfig): FixResult

Parameters

text
string
required
The translation text to fix. Should contain speaker-labeled dialogue (e.g., Q&A format, fatwa exchanges).
config
FixConfig
Optional configuration for the fixer.

Return Value

FixResult
object
Object containing the fixed text and metadata.

Examples

Basic Usage

import { fixCollapsedSpeakerLines } from 'wobble-bibble';

const malformed = `P1 - Questioner: What is the ruling? The Shaykh: The ruling is permissible.`;

const result = fixCollapsedSpeakerLines(malformed, {
  speakerLabels: ['Questioner', 'The Shaykh']
});

console.log(result.text);
// P1 - Questioner: What is the ruling?
// The Shaykh: The ruling is permissible.

console.log(result.counts);
// { fixCollapsedSpeakerLines: 1 }

Auto-Inference of Speaker Labels

const text = `
P1 - Questioner: First question?
P2 - The Shaykh: First answer. Questioner: Follow-up question?
P3 - The Shaykh: Final answer.
`;

// No config provided - labels will be inferred
const result = fixCollapsedSpeakerLines(text);

console.log(result.text);
// P1 - Questioner: First question?
// P2 - The Shaykh: First answer.
// Questioner: Follow-up question?
// P3 - The Shaykh: Final answer.

Punctuation Preservation

const text = `P1 - The answer is yes. The Shaykh: However, there are conditions.`;

const result = fixCollapsedSpeakerLines(text, {
  speakerLabels: ['The Shaykh'],
  leadingPunctuation: ['.', '?', '!']
});

console.log(result.text);
// P1 - The answer is yes.
// The Shaykh: However, there are conditions.
// Note: The period is preserved before the newline

Multiple Collapses on One Line

const text = `P1 - Questioner: Question one? The Shaykh: Answer one. Questioner: Question two?`;

const result = fixCollapsedSpeakerLines(text, {
  speakerLabels: ['Questioner', 'The Shaykh']
});

console.log(result.text);
// P1 - Questioner: Question one?
// The Shaykh: Answer one.
// Questioner: Question two?

console.log(result.counts);
// { fixCollapsedSpeakerLines: 2 }

No Fixes Needed

const wellFormatted = `
P1 - Questioner: What is the ruling?
P2 - The Shaykh: The ruling is permissible.
`;

const result = fixCollapsedSpeakerLines(wellFormatted);

console.log(result.applied);
// []

console.log(result.counts);
// { fixCollapsedSpeakerLines: 0 }

console.log(result.text === wellFormatted);
// true (text unchanged)

Behavior Details

Label Detection

The function only inserts newlines before labels that appear mid-line (not at the start of a line):
const text = `Questioner: This is fine. The Shaykh: This needs fixing.`;
//            ^^^^^^^^^^^ already at line start - ignored
//                                      ^^^^^^^^^^^ mid-line - fixed

Segment ID Preservation

The function preserves segment IDs and only processes the text after the ID:
const text = `P123 - Questioner: Text here. The Shaykh: More text.`;
//            ^^^^^^^ preserved as-is

Empty Label List Handling

If no speaker labels are found (either provided or inferred), the function returns the original text unchanged:
const text = `P1 - Some text without any speaker labels.`;

const result = fixCollapsedSpeakerLines(text);
// No labels found, nothing to fix

console.log(result.text === text);
// true

console.log(result.counts);
// { fixCollapsedSpeakerLines: 0 }

Trailing Whitespace Handling

When inserting newlines, trailing whitespace before the label is removed:
const text = `P1 - Answer.    The Shaykh: Text.`;
//                      ^^^^ extra spaces removed

const result = fixCollapsedSpeakerLines(text, {
  speakerLabels: ['The Shaykh']
});

console.log(result.text);
// P1 - Answer.
// The Shaykh: Text.

Validation Error Type

This fixer corresponds to the collapsed_speakers validation error type:
import { validateTranslation, fixAll } from 'wobble-bibble';

// 1. Validate to detect the error
const validation = validateTranslation(llmOutput, segments, config);
const hasCollapsed = validation.errors.some(e => e.type === 'collapsed_speakers');

// 2. Fix if detected
if (hasCollapsed) {
  const fixed = fixAll(llmOutput, {
    types: ['collapsed_speakers'],
    config: { speakerLabels: ['Questioner', 'The Shaykh'] }
  });
  console.log(fixed.text);
}

Build docs developers (and LLMs) love