Skip to content

Commit

Permalink
Merge pull request Redocly#7 from databricks/linkable-fields
Browse files Browse the repository at this point in the history
linkable fields
  • Loading branch information
dvkuznietsov authored Dec 18, 2022
2 parents 9cbd7a9 + c7414c1 commit fb5a621
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 10 deletions.
8 changes: 6 additions & 2 deletions src/components/Fields/Field.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,19 @@ export class Field extends React.Component<FieldProps> {
onKeyPress={this.handleKeyPress}
aria-label="expand properties"
>
<span className="text code">{name}</span>
<span className="text code" id={field.path}>
{name}
</span>
<ShelfIcon direction={expanded ? 'down' : 'right'} />
</label>
{labels}
{availability && <span className="text info">{availability} preview</span>}
</div>
) : (
<div className={classNames(deprecated ? 'deprecated' : undefined, 'property-name-cell')}>
<span className="text code">{name}</span>
<span className="text code" id={field.path}>
{name}
</span>
{labels}
</div>
);
Expand Down
1 change: 1 addition & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export * from './Markdown/AdvancedMarkdown';
export { StyledMarkdownBlock } from './Markdown/styled.elements';
export * from './SecuritySchemes/SecuritySchemes';
export * from './Endpoint/Endpoint';
export * from './Endpoint/styled.elements';
export * from './ExternalDocumentation/ExternalDocumentation';
export * from './Fields/Extensions';
export * from './SecurityRequirement/SecurityRequirement';
Expand Down
18 changes: 13 additions & 5 deletions src/services/MarkdownRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,33 @@ const methodLink = {
return src.match(/:/)?.index;
},
tokenizer(src) {
const link = /^:(method|schema):([a-zA-Z0-9]*)/;
const link = /^:(method|schema):([a-zA-Z0-9]*)(#[a-zA-Z\\\/_]*)?/;
const match = link.exec(src);
if (match) {
return {
type: 'methodLink',
raw: match[0],
dt: this.lexer.inlineTokens(match[1].trim()),
dd: this.lexer.inlineTokens(match[2].trim()),
da: match[3] ? this.lexer.inlineTokens(match[3].trim()) : undefined,
};
}
},
renderer(token) {
// the last string in the path should be displayed
const displayText = this.parser.parseInline(token.dd).split('/').pop();
return `<a href="" data-id="markdown-link" data-url-entity="${this.parser.parseInline(
let displayText = this.parser.parseInline(token.dd).split('/').pop();

if (token.da) {
displayText = this.parser.parseInline(token.da).split('/').pop();
}

return `<a href="#" data-id="markdown-link" data-url-entity="${this.parser.parseInline(
token.dt,
)}" data-url="${this.parser.parseInline(token.dd)}">${displayText}</a>`;
)}" data-url="${this.parser.parseInline(token.dd)}${
token.da ? this.parser.parseInline(token.da) : ''
}">${displayText}</a>`;
},
childTokens: ['dt', 'dd'],
childTokens: ['dt', 'dd', 'da'],
};

marked.use({ renderer, extensions: [methodLink] });
Expand Down
14 changes: 13 additions & 1 deletion src/services/models/Field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export class FieldModel {
explode: boolean;
style?: OpenAPIParameterStyle;
const?: any;
path?: string;

serializationMime?: string;

Expand All @@ -65,6 +66,7 @@ export class FieldModel {
pointer: string,
options: RedocNormalizedOptions,
refsStack?: string[],
parentPath?: string,
) {
makeObservable(this);

Expand All @@ -74,14 +76,24 @@ export class FieldModel {
this.in = info.in;
this.required = !!info.required;

this.path = `${parentPath ? parentPath + '/' : ''}${this.name}`;

let fieldSchema = info.schema;
let serializationMime = '';
if (!fieldSchema && info.in && info.content) {
serializationMime = Object.keys(info.content)[0];
fieldSchema = info.content[serializationMime] && info.content[serializationMime].schema;
}

this.schema = new SchemaModel(parser, fieldSchema || {}, pointer, options, false, refsStack);
this.schema = new SchemaModel(
parser,
fieldSchema || {},
pointer,
options,
false,
refsStack,
this.path,
);
this.description =
info.description === undefined ? this.schema.description || '' : info.description;
this.example = info.example || this.schema.example;
Expand Down
35 changes: 33 additions & 2 deletions src/services/models/Schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export class SchemaModel {
contentMediaType?: string;
minItems?: number;
maxItems?: number;
path?: string;

/**
* @param isChild if schema discriminator Child
Expand All @@ -82,10 +83,12 @@ export class SchemaModel {
private options: RedocNormalizedOptions,
isChild: boolean = false,
private refsStack: string[] = [],
parentPath?: string,
) {
makeObservable(this);

this.pointer = schemaOrRef.$ref || pointer || '';
this.path = parentPath;

const { resolved, refsStack: newRefsStack } = parser.deref(schemaOrRef, refsStack, true);
this.refsStack = pushRef(newRefsStack, this.pointer);
Expand Down Expand Up @@ -191,10 +194,24 @@ export class SchemaModel {
}

if (this.hasType('object')) {
this.fields = buildFields(parser, schema, this.pointer, this.options, this.refsStack);
this.fields = buildFields(
parser,
schema,
this.pointer,
this.options,
this.refsStack,
this.path,
);
} else if (this.hasType('array')) {
if (isArray(schema.items) || isArray(schema.prefixItems)) {
this.fields = buildFields(parser, schema, this.pointer, this.options, this.refsStack);
this.fields = buildFields(
parser,
schema,
this.pointer,
this.options,
this.refsStack,
this.path,
);
} else if (schema.items) {
this.items = new SchemaModel(
parser,
Expand All @@ -203,6 +220,7 @@ export class SchemaModel {
this.options,
false,
this.refsStack,
this.path,
);
}

Expand Down Expand Up @@ -260,6 +278,7 @@ export class SchemaModel {
this.options,
false,
refsStack,
this.path,
);

return schema;
Expand Down Expand Up @@ -377,6 +396,7 @@ export class SchemaModel {
this.options,
true,
this.refsStack.slice(0, -1),
this.path,
);
innerSchema.title = name;
return innerSchema;
Expand Down Expand Up @@ -412,6 +432,7 @@ export class SchemaModel {
this.options,
false,
this.refsStack,
this.path,
),
);
this.oneOfType = 'One of';
Expand All @@ -424,6 +445,7 @@ function buildFields(
$ref: string,
options: RedocNormalizedOptions,
refsStack: string[],
path?: string,
): FieldModel[] {
const props = schema.properties || schema.prefixItems || schema.items || {};
const patternProps = schema.patternProperties || {};
Expand Down Expand Up @@ -456,6 +478,7 @@ function buildFields(
$ref + '/properties/' + fieldName,
options,
refsStack,
path,
);
});

Expand Down Expand Up @@ -489,6 +512,7 @@ function buildFields(
`${$ref}/patternProperties/${fieldName}`,
options,
refsStack,
path,
);
}),
);
Expand All @@ -509,6 +533,7 @@ function buildFields(
$ref + '/additionalProperties',
options,
refsStack,
path,
),
);
}
Expand All @@ -521,6 +546,7 @@ function buildFields(
$ref,
options,
refsStack,
path,
}),
);

Expand All @@ -534,13 +560,15 @@ function buildAdditionalItems({
$ref,
options,
refsStack,
path,
}: {
parser: OpenAPIParser;
schema?: OpenAPISchema | OpenAPISchema[] | boolean;
fieldsCount: number;
$ref: string;
options: RedocNormalizedOptions;
refsStack: string[];
path?: string;
}) {
if (isBoolean(schema)) {
return schema
Expand All @@ -554,6 +582,7 @@ function buildAdditionalItems({
`${$ref}/additionalItems`,
options,
refsStack,
path,
),
]
: [];
Expand All @@ -572,6 +601,7 @@ function buildAdditionalItems({
`${$ref}/additionalItems`,
options,
refsStack,
path,
),
),
];
Expand All @@ -588,6 +618,7 @@ function buildAdditionalItems({
`${$ref}/additionalItems`,
options,
refsStack,
path,
),
];
}
Expand Down

0 comments on commit fb5a621

Please sign in to comment.