Skip to content

Commit 9ede433

Browse files
authored
fix: Coalesce adjacent field labels (#9996)
* fix: Coalesce adjacent field labels * fix: removed old commented-out line * fix: removed unnecessary @internal decorators and changed test from xml to functional block creation
1 parent 26a2550 commit 9ede433

2 files changed

Lines changed: 147 additions & 13 deletions

File tree

packages/blockly/core/block_aria_composer.ts

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,8 +318,81 @@ export function getInputLabels(
318318
);
319319
}
320320
}
321+
let adjacentFieldLabels: Array<string> = [];
322+
return inputsToLabel.flatMap((input, index, inputs) => {
323+
const inputLabel = input.getLabel(verbosity);
324+
if (
325+
index < inputs.length - 1 &&
326+
endsWithFieldLabel(input) &&
327+
beginsWithFieldLabel(inputs[index + 1]) &&
328+
!isEndOfRow(input, inputs[index + 1])
329+
) {
330+
// This input ends with a field label and the next one begins with one.
331+
// They are also on the same visual row. We want to combine these, so we
332+
// add this one to the list for later handling. Value inputs are
333+
// excluded from this as the value should be separated.
334+
adjacentFieldLabels.push(inputLabel);
335+
return [];
336+
} else if (beginsWithFieldLabel(input) && adjacentFieldLabels.length > 0) {
337+
// There is at least one adjacent FieldLabel before this one but none
338+
// after. Combine the FieldLabels into one string.
339+
adjacentFieldLabels.push(inputLabel);
340+
const label = adjacentFieldLabels.join(' ');
341+
adjacentFieldLabels = [];
342+
return label;
343+
}
344+
return inputLabel;
345+
});
346+
}
321347

322-
return inputsToLabel.map((input) => input.getLabel(verbosity));
348+
/**
349+
* Returns whether an input's list of visible fields begins with a FieldLabel
350+
*
351+
* @param input the input to be evaluated
352+
* @returns a boolean indicating whether the input's first visible field is of
353+
* type FieldLabel
354+
*/
355+
function beginsWithFieldLabel(input: Input): boolean {
356+
const visibleFields = input.fieldRow.filter((field) => field.isVisible());
357+
return visibleFields.length > 0 && visibleFields[0] instanceof FieldLabel;
358+
}
359+
360+
/**
361+
* Returns whether an input's list of visible fields ends with a FieldLabel
362+
*
363+
* @param input the input to be evaluated
364+
* @returns a boolean indicating whether the input's last visible field is of
365+
* type FieldLabel
366+
*/
367+
function endsWithFieldLabel(input: Input): boolean {
368+
// Values and statements never have a label at the end of the input.
369+
if (input.type === inputTypes.VALUE || input.type === inputTypes.STATEMENT) {
370+
return false;
371+
}
372+
const visibleFields = input.fieldRow.filter((field) => field.isVisible());
373+
return (
374+
visibleFields.length > 0 &&
375+
visibleFields[visibleFields.length - 1] instanceof FieldLabel
376+
);
377+
}
378+
379+
/**
380+
* Returns whether the current input is the end of a visual "row"
381+
*
382+
* @param current the input of which to evaluate the end-of-row status
383+
* @param next the next input on the block after "current"
384+
* @returns a boolean representation of whether "current" is the end of a row
385+
*/
386+
function isEndOfRow(current: Input, next: Input): boolean {
387+
const precedingStatementInput =
388+
current.connection?.type === ConnectionType.NEXT_STATEMENT ||
389+
current.type === inputTypes.END_ROW;
390+
391+
return (
392+
!current.getSourceBlock().getInputsInline() ||
393+
next.connection?.type === ConnectionType.NEXT_STATEMENT ||
394+
precedingStatementInput
395+
);
323396
}
324397

325398
/**

packages/blockly/tests/mocha/input_test.js

Lines changed: 73 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -379,19 +379,80 @@ suite('Inputs', function () {
379379

380380
assert.include(label, 'first, 0');
381381
});
382-
test('Adjacent labels for FieldLabels are combined into one field.', function () {
383-
this.block
384-
.appendDummyInput()
385-
.appendField('first')
386-
.appendField('second')
387-
.appendField(new Blockly.FieldNumber(0))
388-
.appendField('third')
389-
.appendField('fourth')
390-
.appendField('fifth');
382+
suite(
383+
'Adjacent labels for FieldLabels are combined into one field',
384+
function () {
385+
test('Value inputs are not combined', function () {
386+
this.block.appendDummyInput().appendField('first');
387+
this.block.appendValueInput('number').appendField('second');
388+
this.block
389+
.appendDummyInput()
390+
.appendField('third')
391+
.appendField('fourth');
392+
393+
const label = this.block.getAriaLabel();
394+
395+
assert.include(label, 'first second,');
396+
assert.include(label, 'third fourth');
397+
});
398+
test('Statement inputs are not combined', function () {
399+
const statementBlock = createRenderedBlock(
400+
this.workspace,
401+
'empty_block',
402+
);
403+
statementBlock.appendDummyInput().appendField('first');
404+
statementBlock
405+
.appendStatementInput('statement')
406+
.appendField('second');
407+
statementBlock
408+
.appendDummyInput()
409+
.appendField('third')
410+
.appendField('fourth');
411+
statementBlock.setPreviousStatement(true);
412+
statementBlock.setNextStatement(true);
413+
414+
const label = statementBlock.getAriaLabel();
415+
416+
assert.include(label, 'first, second, third fourth');
417+
});
418+
test('Dummy inputs on the same row are combined', function () {
419+
this.block.appendDummyInput().appendField('first');
420+
this.block.appendDummyInput().appendField('second');
421+
this.block
422+
.appendDummyInput()
423+
.appendField('third')
424+
.appendField('fourth');
425+
this.block.setInputsInline(true);
426+
427+
const label = this.block.getAriaLabel();
428+
429+
assert.include(label, 'first second third fourth');
430+
});
431+
test('Dummy inputs on different rows are not combined', function () {
432+
this.block.appendDummyInput().appendField('first');
433+
this.block.appendDummyInput().appendField('second');
434+
this.block
435+
.appendDummyInput()
436+
.appendField('third')
437+
.appendField('fourth');
391438

392-
const label = this.block.getAriaLabel();
439+
const label = this.block.getAriaLabel();
393440

394-
assert.include(label, 'first second, 0, third fourth fifth');
395-
});
441+
assert.include(label, 'first, second, third fourth');
442+
});
443+
test('End row inputs are not combined', function () {
444+
this.block.appendDummyInput().appendField('first');
445+
this.block.appendEndRowInput('endRowInput').appendField('second');
446+
this.block
447+
.appendDummyInput()
448+
.appendField('third')
449+
.appendField('fourth');
450+
451+
const label = this.block.getAriaLabel();
452+
453+
assert.include(label, 'first second, third fourth');
454+
});
455+
},
456+
);
396457
});
397458
});

0 commit comments

Comments
 (0)