mirror of
https://github.com/Redocly/redoc.git
synced 2025-02-17 02:10:39 +03:00
fix: use original tag name when slugified one is not valid (#553)
* use original tag name when slugified one is not valid * use wrapper function when using slugify
This commit is contained in:
parent
76906eb126
commit
8817d9c9db
|
@ -1,7 +1,6 @@
|
||||||
import * as marked from 'marked';
|
import * as marked from 'marked';
|
||||||
import slugify from 'slugify';
|
|
||||||
|
|
||||||
import { highlight, html2Str } from '../utils';
|
import { highlight, html2Str, safeSlugify } from '../utils';
|
||||||
import { AppStore } from './AppStore';
|
import { AppStore } from './AppStore';
|
||||||
import { SECTION_ATTR } from './MenuStore';
|
import { SECTION_ATTR } from './MenuStore';
|
||||||
|
|
||||||
|
@ -56,7 +55,7 @@ export class MarkdownRenderer {
|
||||||
parentId?: string,
|
parentId?: string,
|
||||||
): MarkdownHeading {
|
): MarkdownHeading {
|
||||||
const item = {
|
const item = {
|
||||||
id: parentId ? `${parentId}/${slugify(name)}` : `section/${slugify(name)}`,
|
id: parentId ? `${parentId}/${safeSlugify(name)}` : `section/${safeSlugify(name)}`,
|
||||||
name,
|
name,
|
||||||
items: [],
|
items: [],
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { action, observable } from 'mobx';
|
import { action, observable } from 'mobx';
|
||||||
import slugify from 'slugify';
|
|
||||||
|
|
||||||
import { OpenAPIExternalDocumentation, OpenAPITag } from '../../types';
|
import { OpenAPIExternalDocumentation, OpenAPITag } from '../../types';
|
||||||
|
import { safeSlugify } from '../../utils';
|
||||||
import { MarkdownHeading } from '../MarkdownRenderer';
|
import { MarkdownHeading } from '../MarkdownRenderer';
|
||||||
import { ContentItemModel } from '../MenuBuilder';
|
import { ContentItemModel } from '../MenuBuilder';
|
||||||
import { IMenuItem, MenuItemGroupType } from '../MenuStore';
|
import { IMenuItem, MenuItemGroupType } from '../MenuStore';
|
||||||
|
@ -32,7 +32,7 @@ export class GroupModel implements IMenuItem {
|
||||||
parent?: GroupModel,
|
parent?: GroupModel,
|
||||||
) {
|
) {
|
||||||
// markdown headings already have ids calculated as they are needed for heading anchors
|
// markdown headings already have ids calculated as they are needed for heading anchors
|
||||||
this.id = (tagOrGroup as MarkdownHeading).id || type + '/' + slugify(tagOrGroup.name);
|
this.id = (tagOrGroup as MarkdownHeading).id || type + '/' + safeSlugify(tagOrGroup.name);
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.name = tagOrGroup['x-displayName'] || tagOrGroup.name;
|
this.name = tagOrGroup['x-displayName'] || tagOrGroup.name;
|
||||||
this.description = tagOrGroup.description || '';
|
this.description = tagOrGroup.description || '';
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { mapWithLast, appendToMdHeading, mergeObjects } from '../helpers';
|
import slugify from 'slugify';
|
||||||
|
import { mapWithLast, appendToMdHeading, mergeObjects, safeSlugify } from '../helpers';
|
||||||
|
|
||||||
describe('Utils', () => {
|
describe('Utils', () => {
|
||||||
describe('helpers', () => {
|
describe('helpers', () => {
|
||||||
|
@ -39,6 +40,16 @@ describe('Utils', () => {
|
||||||
expect(val).toEqual('# Authentication\n\n<test>');
|
expect(val).toEqual('# Authentication\n\n<test>');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('slugifyIfAvailable returns original value when cannot slugify the value', () => {
|
||||||
|
const willBeSlugifed = safeSlugify('some string')
|
||||||
|
expect(willBeSlugifed).toEqual('some-string');
|
||||||
|
|
||||||
|
const cannotBeSlugified = '가나다라 마바사'
|
||||||
|
// if slugify() fixes this issue, safeSlugify should be removed and replaced with original one.
|
||||||
|
expect(slugify(cannotBeSlugified)).toEqual('');
|
||||||
|
expect(safeSlugify(cannotBeSlugified)).toEqual('가나다라-마바사');
|
||||||
|
})
|
||||||
|
|
||||||
describe('mergeObjects', () => {
|
describe('mergeObjects', () => {
|
||||||
test('should merge Objects and all nested Ones', () => {
|
test('should merge Objects and all nested Ones', () => {
|
||||||
const obj1 = { a: { a1: 'A1' }, c: 'C', d: {} };
|
const obj1 = { a: { a1: 'A1' }, c: 'C', d: {} };
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import slugify from 'slugify';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps over array passing `isLast` bool to iterator as the second arguemnt
|
* Maps over array passing `isLast` bool to iterator as the second arguemnt
|
||||||
*/
|
*/
|
||||||
|
@ -116,3 +118,18 @@ const isObject = (item: any): boolean => {
|
||||||
const isMergebleObject = (item): boolean => {
|
const isMergebleObject = (item): boolean => {
|
||||||
return isObject(item) && !Array.isArray(item);
|
return isObject(item) && !Array.isArray(item);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* slugify() returns empty string when failed to slugify.
|
||||||
|
* so try to return minimun slugified-string with failed one which keeps original value
|
||||||
|
* the regex codes are referenced with https://gist.github.com/mathewbyrne/1280286
|
||||||
|
*/
|
||||||
|
export function safeSlugify(value: string): string {
|
||||||
|
return slugify(value) ||
|
||||||
|
value.toString().toLowerCase()
|
||||||
|
.replace(/\s+/g, '-') // Replace spaces with -
|
||||||
|
.replace(/&/g, '-and-') // Replace & with 'and'
|
||||||
|
.replace(/\--+/g, '-') // Replace multiple - with single -
|
||||||
|
.replace(/^-+/, '') // Trim - from start of text
|
||||||
|
.replace(/-+$/, ''); // Trim - from end of text
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user