Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## unreleased

- CLI: Fix YAML output to keep quotes for $ref values (#230)

## [1.33.4] - 2026-06-19

- CLI: add yamlCompat option for YAML 1.1
Expand Down
6 changes: 3 additions & 3 deletions test/_split/snap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ info:
description: A compact version of the Train Travel API
paths:
/stations/{station_id}:
$ref: paths/stations_{station_id}.yaml
$ref: 'paths/stations_{station_id}.yaml'
components:
schemas:
Station:
$ref: components/schemas/Station.yaml
$ref: 'components/schemas/Station.yaml'
parameters:
StationId:
$ref: components/parameters/StationId.yaml
$ref: 'components/parameters/StationId.yaml'
4 changes: 2 additions & 2 deletions test/_split/snap_station.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ get:
summary: Get station information
operationId: getStation
parameters:
- $ref: ../components/parameters/StationId.yaml
- $ref: '../components/parameters/StationId.yaml'
responses:
'200':
description: Successful operation
content:
application/json:
schema:
$ref: ../components/schemas/Station.yaml
$ref: '../components/schemas/Station.yaml'
'404':
description: Station not found
47 changes: 47 additions & 0 deletions test/util-file.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,53 @@ describe('openapi-format CLI file tests', () => {

expect(result).toContain("$ref: '#/components/schemas/Example'");
});

test('should stringify external $ref values with quotes in YAML output', async () => {
const obj = {
paths: {
'/some/path': {
get: {
parameters: [
{
$ref: './util/headers.yaml#/components/parameters/requestId'
}
]
}
}
}
};

const result = await stringify(obj, {format: 'yaml'});

expect(result).toContain(
"$ref: './util/headers.yaml#/components/parameters/requestId'"
);
});

test('should stringify external $ref values with the configured double quote style', async () => {
const obj = {
paths: {
'/some/path': {
get: {
parameters: [
{
$ref: './util/headers.yaml#/components/parameters/requestId'
}
]
}
}
}
};

const result = await stringify(obj, {
format: 'yaml',
yamlQuoteStyle: 'double'
});

expect(result).toContain(
'$ref: "./util/headers.yaml#/components/parameters/requestId"'
);
});
});

describe('analyzeOpenApi function', () => {
Expand Down
14 changes: 14 additions & 0 deletions test/yaml-path-ref-quotes/input.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
openapi: 3.0.3
info:
title: API
version: 1.0.0
paths:
/some/path:
get:
operationId: someOperation
tags:
- some-rest-controller
parameters:
- $ref: "./util/headers.yaml#/components/parameters/requestId"
- $ref: './util/headers.yaml#/components/parameters/correlationId'
- $ref: ./util/headers.yaml#/components/parameters/authorization
4 changes: 4 additions & 0 deletions test/yaml-path-ref-quotes/options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
verbose: true
output: output.yaml
bundle: false
no-sort: true
14 changes: 14 additions & 0 deletions test/yaml-path-ref-quotes/output.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
openapi: 3.0.3
info:
title: API
version: 1.0.0
paths:
/some/path:
get:
operationId: someOperation
tags:
- some-rest-controller
parameters:
- $ref: './util/headers.yaml#/components/parameters/requestId'
- $ref: './util/headers.yaml#/components/parameters/correlationId'
- $ref: './util/headers.yaml#/components/parameters/authorization'
4 changes: 2 additions & 2 deletions test/yaml-ref-quotes/output.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ components:
type: object
properties:
extern:
$ref: domain-types.openapi.yaml#/components/schemas/Extern
$ref: 'domain-types.openapi.yaml#/components/schemas/Extern'
intern:
$ref: domain-types.openapi.yaml#/components/schemas/Extern
$ref: 'domain-types.openapi.yaml#/components/schemas/Extern'
8 changes: 6 additions & 2 deletions utils/file.js
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,9 @@ async function stringify(obj, options = {}) {
output = newDoc.toString(yamlStringifyOptions);
}

// Preserve quotes around $ref values so external references stay editor-friendly.
output = addQuotesToRefInString(output, yamlStringifyOptions.singleQuote ? "'" : '"');

// Decode large number YAML values safely before writing output
output = decodeLargeNumbers(output);
} else {
Expand Down Expand Up @@ -744,10 +747,11 @@ function decodeLargeNumbers(output, isJson = false) {
/**
* Add quotes to $ref in string
* @param {string} yamlString - The input YAML string.
* @param {string} quoteChar - Quote character to use around $ref values.
* @returns {string} YAML string with quotes.
*/
function addQuotesToRefInString(yamlString) {
return yamlString.replace(/(\$ref:\s*)([^"'\s>]+)/g, "$1'$2'");
function addQuotesToRefInString(yamlString, quoteChar = "'") {
return yamlString.replace(/(\$ref:\s*)([^"'\s>]+)/g, `$1${quoteChar}$2${quoteChar}`);
}

/**
Expand Down
Loading