1
0
mirror of synced 2025-12-23 11:54:18 -05:00

Unique headers for REST operation components (#34986)

This commit is contained in:
Hector Alfaro
2023-02-27 14:07:56 -05:00
committed by GitHub
parent 67d8cf54a1
commit d34829ed16
7 changed files with 91 additions and 29 deletions

View File

@@ -20,6 +20,7 @@ import { useVersion } from 'components/hooks/useVersion'
type Props = { type Props = {
slug: string slug: string
operation: Operation operation: Operation
heading: string
} }
const GHCLIKEY = 'ghcli' const GHCLIKEY = 'ghcli'
@@ -41,7 +42,7 @@ function getLanguageHighlight(selectedLanguage: string) {
return selectedLanguage === JSKEY ? 'javascript' : 'curl' return selectedLanguage === JSKEY ? 'javascript' : 'curl'
} }
export function RestCodeSamples({ operation, slug }: Props) { export function RestCodeSamples({ operation, slug, heading }: Props) {
const { t } = useTranslation('products') const { t } = useTranslation('products')
const { isEnterpriseServer } = useVersion() const { isEnterpriseServer } = useVersion()
@@ -228,7 +229,7 @@ export function RestCodeSamples({ operation, slug }: Props) {
return ( return (
<> <>
<h3 className="mt-0 pt-0 h4" id={`${slug}--code-samples`}> <h3 className="mt-0 pt-0 h4" id={`${slug}--code-samples`}>
<a href={`#${slug}--code-samples`}>{`${t('rest.reference.code_samples')}`}</a> <a href={`#${slug}--code-samples`}>{heading}</a>
</h3> </h3>
{/* Display an example selector if more than one example */} {/* Display an example selector if more than one example */}
@@ -299,11 +300,12 @@ export function RestCodeSamples({ operation, slug }: Props) {
</div> </div>
{/* Response section */} {/* Response section */}
<h5 <div
className="mt-5 mb-2 h5"
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: displayedExample.response.description || t('rest.reference.response'), __html: displayedExample.response.description || t('rest.reference.response'),
}} }}
></h5> ></div>
<div className="border rounded-1"> <div className="border rounded-1">
{displayedExample.response.schema ? ( {displayedExample.response.schema ? (

View File

@@ -67,7 +67,10 @@ export function RestOperation({ operation }: Props) {
<ParameterTable <ParameterTable
slug={titleSlug} slug={titleSlug}
numPreviews={numPreviews} numPreviews={numPreviews}
heading={t('rest.reference.parameters')} heading={t('rest.reference.parameters').replace(
'{{ RESTOperationTitle }}',
operation.title
)}
headers={headers} headers={headers}
parameters={operation.parameters} parameters={operation.parameters}
bodyParameters={operation.bodyParameters} bodyParameters={operation.bodyParameters}
@@ -75,16 +78,48 @@ export function RestOperation({ operation }: Props) {
)} )}
{hasStatusCodes && ( {hasStatusCodes && (
<RestStatusCodes statusCodes={operation.statusCodes} slug={titleSlug} /> <RestStatusCodes
statusCodes={operation.statusCodes}
slug={titleSlug}
heading={t('rest.reference.http_status_code').replace(
'{{ RESTOperationTitle }}',
operation.title
)}
/>
)} )}
</div> </div>
<div <div
className="col-md-12 col-lg-6 position-sticky flex-self-start" className="col-md-12 col-lg-6 position-sticky flex-self-start"
style={{ top: '6.5em' }} style={{ top: '6.5em' }}
> >
{hasCodeSamples && <RestCodeSamples operation={operation} slug={titleSlug} />} {hasCodeSamples && (
<RestCodeSamples
operation={operation}
slug={titleSlug}
heading={t('rest.reference.code_samples').replace(
'{{ RESTOperationTitle }}',
operation.title
)}
/>
)}
{numPreviews > 0 && <RestPreviewNotice slug={titleSlug} previews={operation.previews} />} {numPreviews > 0 && (
<RestPreviewNotice
slug={titleSlug}
previews={operation.previews}
heading={
operation.previews.length > 1
? `${t('rest.reference.preview_notices').replace(
'{{ RESTOperationTitle }}',
operation.title
)}`
: `${t('rest.reference.preview_notice').replace(
'{{ RESTOperationTitle }}',
operation.title
)}`
}
/>
)}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,20 +1,14 @@
import { useTranslation } from 'components/hooks/useTranslation'
type Props = { type Props = {
slug: string slug: string
previews: Array<string> previews: Array<string>
heading: string
} }
export function RestPreviewNotice({ slug, previews }: Props) { export function RestPreviewNotice({ slug, previews, heading }: Props) {
const { t } = useTranslation('products')
return ( return (
<> <>
<h3 className="h4" id={`${slug}-preview-notices`}> <h3 className="h4" id={`${slug}-preview-notices`}>
<a href={`#${slug}-preview-notices`}> <a href={`#${slug}-preview-notices`}>{heading}</a>
{previews.length > 1
? `${t('rest.reference.preview_notices')}`
: `${t('rest.reference.preview_notice')}`}
</a>
</h3> </h3>
{previews.map((preview, index) => ( {previews.map((preview, index) => (
<div <div

View File

@@ -4,15 +4,16 @@ import { StatusCode } from './types'
type Props = { type Props = {
statusCodes: Array<StatusCode> statusCodes: Array<StatusCode>
slug: string slug: string
heading: string
} }
export function RestStatusCodes({ statusCodes, slug }: Props) { export function RestStatusCodes({ statusCodes, slug, heading }: Props) {
const { t } = useTranslation('products') const { t } = useTranslation('products')
return ( return (
<> <>
<h3 className="mt-4 mb-3 pt-3 h4" id={`${slug}--status-codes`}> <h3 className="mt-4 mb-3 pt-3 h4" id={`${slug}--status-codes`}>
<a href={`#${slug}--status-codes`}>{t('rest.reference.http_status_code')}</a> <a href={`#${slug}--status-codes`}>{heading}</a>
</h3> </h3>
<table> <table>

View File

@@ -133,15 +133,15 @@ products:
in: In in: In
description: Description description: Description
notes: Notes notes: Notes
parameters: Parameters parameters: Parameters for "{{ RESTOperationTitle }}"
response: Response response: Response
example_response: Example response example_response: Example response
status_code: Status code status_code: Status code
http_status_code: HTTP response status codes http_status_code: HTTP response status codes for "{{ RESTOperationTitle }}"
code_sample: Code sample code_sample: Code sample
code_samples: Code samples code_samples: Code samples for "{{ RESTOperationTitle }}"
preview_notice: Preview notice preview_notice: Preview notice for "{{ RESTOperationTitle }}"
preview_notices: Preview notices preview_notices: Preview notices for "{{ RESTOperationTitle }}"
preview_header_is_required: This header is <strong>required</strong> preview_header_is_required: This header is <strong>required</strong>
preview_notice_to_change: This API is under preview and subject to change preview_notice_to_change: This API is under preview and subject to change
works_with: Works with works_with: Works with

View File

@@ -133,15 +133,15 @@ products:
in: In in: In
description: Description description: Description
notes: Notes notes: Notes
parameters: Parameters parameters: Parameters for "{{ RESTOperationTitle }}"
response: Response response: Response
example_response: Example response example_response: Example response
status_code: Status code status_code: Status code
http_status_code: HTTP response status codes http_status_code: HTTP response status codes for "{{ RESTOperationTitle }}"
code_sample: Code sample code_sample: Code sample
code_samples: Code samples code_samples: Code samples for "{{ RESTOperationTitle }}"
preview_notice: Preview notice preview_notice: Preview notice for "{{ RESTOperationTitle }}"
preview_notices: Preview notices preview_notices: Preview notices for "{{ RESTOperationTitle }}"
preview_header_is_required: This header is <strong>required</strong> preview_header_is_required: This header is <strong>required</strong>
preview_notice_to_change: This API is under preview and subject to change preview_notice_to_change: This API is under preview and subject to change
works_with: Works with works_with: Works with

View File

@@ -152,6 +152,36 @@ describe('REST references docs', () => {
} }
} }
}) })
describe('headings', () => {
test('rest pages do not render any headings with duplicate text', async () => {
const $ = await getDOM('/en/rest/actions/artifacts')
const headingText = $('body')
.find('h2, h3, h4, h5, h6')
.map((i, el) => $(el).text())
.get()
.sort()
const dupes = headingText.filter((item, index) => headingText.indexOf(item) !== index)
const message = `The following duplicate heading texts were found: ${dupes.join(', ')}`
expect(dupes.length, message).toBe(0)
})
test('rest pages do not render any headings with duplicate ids', async () => {
const $ = await getDOM('/en/rest/actions/artifacts')
const headingIDs = $('body')
.find('h2, h3, h4, h5, h6')
.map((i, el) => $(el).attr('id'))
.get()
.sort()
const dupes = headingIDs.filter((item, index) => headingIDs.indexOf(item) !== index)
const message = `The following duplicate heading IDs were found: ${dupes.join(', ')}`
expect(dupes.length, message).toBe(0)
})
})
}) })
function formatErrors(differences) { function formatErrors(differences) {