Skip to content

fix: separate multiple schema examples when displaying them - #317

Open
nimbly1 wants to merge 4 commits into
Authress-Engineering:release/2.4from
nimbly1:fix/issue-316-examples-separator
Open

nimbly1 wants to merge 4 commits into
Authress-Engineering:release/2.4from
nimbly1:fix/issue-316-examples-separator

Conversation

@nimbly1

@nimbly1 nimbly1 commented Oct 4, 2026 •

Copy link
Copy Markdown

Fixes #316

Problem

getTypeInfo() in src/utils/schema-utils.js returned schema.examples or a legacy schema.example through the same example field. The views then wrote that value with ${example} in a Lit template, so examples: ['apple', 'banana', 'pear'] showed Example: applebananapear.

Change

getTypeInfo now returns a list:

  • An examples array is that list.
  • An OpenAPI 3.0 examples map contributes each entry's value. 0 and false are kept. An entry with no value is skipped.
  • A legacy example is one entry, including when that value is itself an array, 0, or false.
  • No example is an empty list. Example generation still runs only when it is asked for and no example is present.

formatExamples() in src/utils/common-utils.js joins that list with ┃, the separator the Allowed row already uses, and writes a non-string as JSON. The schema table, schema tree, and request form show the Example row when that string is non-empty. The request form placeholder and click-to-fill still use the first example. The parameter example list is unchanged: it still uses param.examples, a single param.example, or paramSchema.example.

The issue suggested a pipe-separated list. I used the existing ┃.

History: feb064b joined inside getTypeInfo. 7ec9e50 moved the join to the views. a7cfea5 made getTypeInfo return a list. 00da152 follows the review on that commit: the parameter renderer no longer builds an Example / Example2 map, and the views check the formatExamples string.

Testing

npx ava "tests/**/*.test.js" passes (24 tests). eslint --ext .js on the edited files passes with linebreak-style off, because this Windows checkout has CRLF line endings.

What I did not do: I have not run yarn build and I have not looked at this commit in a browser.

The 2.4 changelog line from the earlier commit is still there.

getTypeInfo returned the `examples` array of a schema unchanged, and the
schema table rendered it as a template value, which joins the entries
with nothing between them ("applebananapear"). Join the entries with the
same separator the Allowed row uses, writing non-string examples as JSON.
A single `example` is left as it was, since an array there is one value.

Fixes Authress-Engineering#316

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Comment thread src/utils/schema-utils.js Outdated
getTypeInfo is the schema evaluator, so it should not build display
text. The previous commit made it join the entries of `examples` into a
string. getTypeInfo is now back to what it was before that commit and
returns the examples of a schema as the schema has them (a list stays a
list).

The views that show the example (schema table, schema tree, response
header table and request form table) now separate the entries of a list
with the new formatExamples helper in common-utils, in the same way
they already separate the allowed values, writing entries that are not
text as JSON. The text shown for a list of `examples` is unchanged from
the previous commit.

Two differences from the previous commit remain. A single `example`
that is itself an array is now shown separated the same way, because
the views cannot tell it from a list of examples (before, it was shown
run together). The placeholders and click-to-fill values of the request
inputs are not touched, so they are again what they were before the
previous commit. An empty `examples` list is again handled as it was
before the previous commit.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Comment thread src/components/request-form-table.js Outdated
this.computeCurlSyntax();
}}">
${type === 'array' ? example.join(', ') : example}
${type === 'array' ? example.join(', ') : formatExamples(example)}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is weird, we need to do sufficient investigation on what should happen here.

@nimbly1 nimbly1 Oct 6, 2026 •

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That branch treated an array schema's example as the list of examples and joined it with commas. The other views used formatExamples. Those are different questions, which is why a single array value and a list of examples could not both be right.

The label now uses formatExamples on the list from getTypeInfo. One example whose value is ['a','b'] stays one example (["a","b"]). Several examples are separated with ┃. The placeholder and the click-to-fill still use the first example only. For an array value, the click still splits that value into the tag input, and the placeholder is still the first item of that value.

Same commit, a7cfea5. I have not looked at this in a browser.

(The first version of this reply was the path of a local file. This is the text it should have been.)

Comment thread src/utils/common-utils.js
}

// The examples of a schema are a list (OpenAPI 3.1), so separate them in the same way the allowed values are, with any that are not text written as JSON
export function formatExamples(examples) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is better, but you'll need to trace all the places where we use the word example back to the source, but the word example makes it assume that we only have one, and this code assumes we have an array, so there is a fundamental mismatch of expectations here.

If examples is called examples then it likely should always be an array, which means code that checks example ?... is wrong, and this code below is also wrong because if examples is not an array then it is nullish. But we already know that is incorrect because since value example still correctly displays, so something else is off here. Look at line 38 in the schema-utils, that's at least one place where there is a problem.

@nimbly1 nimbly1 Oct 6, 2026 •

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mismatch was in getTypeInfo. schema.examples || schema.example stored either a list or a single value in example, so a later check could not tell a list of examples from one example whose value is an array. A real example of 0 or false was also dropped, because both are falsy.

Commit a7cfea5 normalizes that at the source. getTypeInfo now returns a list:

  • an examples array is that list
  • an examples map contributes each entry's value (0 and false stay; an entry with no value is skipped)
  • a legacy example is one entry, including when the value is an array, 0, or false
  • no example is an empty list

formatExamples joins that list. The schema table and schema tree render the Example row only when the list has an entry, so an empty list does not leave a blank Example line. A generated sample is still added only when generation is requested and no example is present.

Unit tests pass (24). I have not run yarn build or looked at this commit in a browser.

(The first version of this reply was the path of a local file. This is the text it should have been.)

@wparad wparad left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to handle the legacy example cases, and the no example cases.

getTypeInfo returns a list. Schema examples stay a list, a legacy example is one entry so an array value is not split, and a missing example is an empty list. The views render that list, and the request form still fills and placeholders from the first example.
Comment thread src/components/api-request.js Outdated

const examples = generateExample(
param.examples || param.example && { Example: { value: param.example } } || paramSchema.examples || paramSchema.example && { Example: { value: paramSchema.example } },
param.examples || param.example && { Example: { value: param.example } } || exampleMap(paramSchema.example),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change feels wrong.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed exampleMap. The parameter example list is back to param.examples, a single param.example, and paramSchema.example. It no longer builds Example / Example2 keys from the normalized list.

Commit 00da152.

Comment thread src/utils/common-utils.js Outdated
return displayExample(examples);
}

// Placeholder text is the first example. An empty list has none.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this comment.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed that comment.

Commit 00da152.

Comment thread src/utils/common-utils.js Outdated
return markdownResult;
}

function displayExample(entry) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
function displayExample(entry) {
function convertToDiplayString(entry) {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed it to convertToDisplayString. The suggestion spelled the name convertToDiplayString, so I used the corrected spelling.

Commit 00da152.

Comment thread src/components/schema-tree.js Outdated
${allowedValues ? html`<div style='display:inline-block; line-break:anywhere; margin-right:8px'><span class='bold-text'>Allowed: </span>${allowedValues.filter(v => v !== null && v !== undefined).join(' ┃ ')}</div><br>` : ''}
${pattern ? html`<div style='display:inline-block; line-break: anywhere; margin-right:8px'><span class='bold-text'>Pattern: </span>${pattern}</div><br>` : ''}
${example ? html`<div style='display:inline-block; line-break: anywhere; margin-right:8px'><span class='bold-text'>Example: </span>${example}</div><br>` : ''}` : ''}
${(Array.isArray(example) ? example.length : example) ? html`<div style='display:inline-block; line-break: anywhere; margin-right:8px'><span class='bold-text'>Example: </span>${formatExamples(example)}</div><br>` : ''}` : ''}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason we cannot just check the formatExamples result instead?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Example row is now shown when formatExamples returns text. An empty list formats to an empty string, so the row stays hidden.

Commit 00da152.

Comment thread src/components/schema-table.js Outdated
${allowedValues ? html`<div style='display:inline-block; line-break: anywhere; margin-right:8px'><span class='bold-text'>Allowed: </span>${allowedValues.filter(v => v !== null && v !== undefined).join(' ┃ ')}</div><br>` : ''}
${pattern ? html`<div style='display:inline-block; line-break: anywhere; margin-right:8px'><span class='bold-text'>Pattern: </span>${pattern}</div><br>` : ''}
${example ? html`<div style='display:inline-block; line-break: anywhere; margin-right:8px'><span class='bold-text'>Example: </span>${example}</div><br>` : ''}
${(Array.isArray(example) ? example.length : example) ? html`<div style='display:inline-block; line-break: anywhere; margin-right:8px'><span class='bold-text'>Example: </span>${formatExamples(example)}</div><br>` : ''}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same, and same goes for all the other places where we do something similar

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same in the schema table and the request form. Both use the formatExamples string instead of checking the array length.

Commit 00da152.

Remove the Example map from the parameter renderer. Show an example when formatExamples returns text, and rename the helper to convertToDisplayString.

@wparad wparad left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there is a lot of cleanup that can be done based on the most recent changes, let me know if I'm missing something.

Comment thread src/utils/common-utils.js
Comment on lines +180 to +186
export function exampleText(examples) {
const value = Array.isArray(examples) ? examples[0] : examples;
if (value === null || value === undefined || value === '') {
return '';
}
return convertToDisplayString(value);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only used in one location it should be moved to the relevant comonent.

const filledExample = Array.isArray(example) ? example[0] : example;
const exampleFill = type === 'array' && Array.isArray(filledExample)
? filledExample.join('~|~')
: (filledExample === null || filledExample === undefined ? '' : (typeof filledExample === 'string' ? filledExample : JSON.stringify(filledExample)));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

convertToDisplayString?

Comment thread src/utils/common-utils.js
Comment on lines +174 to +175
if (examples === null || examples === undefined || examples === '') {
return '';

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels like it belongs in the convertToDisplayString function, thoughts?

const { type, format, readOrWriteOnly, constraints, defaultValue, example, allowedValues, pattern, schemaDescription, schemaTitle, deprecated } = rowData;
const { key, keyLabel, keyDescr, description, dataType, isRequired, options } = parentRecursionOptions;
const exampleLabel = formatExamples(example);
const filledExample = Array.isArray(example) ? example[0] : example;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why wouldn't example always be an array now?

I believe this is coming from the getTypeInfo in the schema util, this is why I suggested renaming the property would be better to help avoid issues like this.

Comment thread src/utils/common-utils.js
}

export function formatExamples(examples) {
if (Array.isArray(examples)) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

examples is a plural parameter, so isn't this always an array?

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Multiple examples are concatenated with no separator

2 participants