From 8817d9c9db820c0e96068e1c04a850715a7d818f Mon Sep 17 00:00:00 2001 From: SeungWoon Maz Lee Date: Tue, 17 Jul 2018 21:21:03 +0900 Subject: [PATCH] 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 --- src/services/MarkdownRenderer.ts | 5 ++--- src/services/models/Group.model.ts | 4 ++-- src/utils/__tests__/helpers.test.ts | 13 ++++++++++++- src/utils/helpers.ts | 17 +++++++++++++++++ 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/services/MarkdownRenderer.ts b/src/services/MarkdownRenderer.ts index 63dceabf4d..56a864a6a7 100644 --- a/src/services/MarkdownRenderer.ts +++ b/src/services/MarkdownRenderer.ts @@ -1,7 +1,6 @@ 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 { SECTION_ATTR } from './MenuStore'; @@ -56,7 +55,7 @@ export class MarkdownRenderer { parentId?: string, ): MarkdownHeading { const item = { - id: parentId ? `${parentId}/${slugify(name)}` : `section/${slugify(name)}`, + id: parentId ? `${parentId}/${safeSlugify(name)}` : `section/${safeSlugify(name)}`, name, items: [], }; diff --git a/src/services/models/Group.model.ts b/src/services/models/Group.model.ts index d2a8d6589d..328ae41f66 100644 --- a/src/services/models/Group.model.ts +++ b/src/services/models/Group.model.ts @@ -1,7 +1,7 @@ import { action, observable } from 'mobx'; -import slugify from 'slugify'; import { OpenAPIExternalDocumentation, OpenAPITag } from '../../types'; +import { safeSlugify } from '../../utils'; import { MarkdownHeading } from '../MarkdownRenderer'; import { ContentItemModel } from '../MenuBuilder'; import { IMenuItem, MenuItemGroupType } from '../MenuStore'; @@ -32,7 +32,7 @@ export class GroupModel implements IMenuItem { parent?: GroupModel, ) { // 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.name = tagOrGroup['x-displayName'] || tagOrGroup.name; this.description = tagOrGroup.description || ''; diff --git a/src/utils/__tests__/helpers.test.ts b/src/utils/__tests__/helpers.test.ts index 17428ca5dc..0b7988b2fe 100644 --- a/src/utils/__tests__/helpers.test.ts +++ b/src/utils/__tests__/helpers.test.ts @@ -1,4 +1,5 @@ -import { mapWithLast, appendToMdHeading, mergeObjects } from '../helpers'; +import slugify from 'slugify'; +import { mapWithLast, appendToMdHeading, mergeObjects, safeSlugify } from '../helpers'; describe('Utils', () => { describe('helpers', () => { @@ -39,6 +40,16 @@ describe('Utils', () => { expect(val).toEqual('# Authentication\n\n'); }); + 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', () => { test('should merge Objects and all nested Ones', () => { const obj1 = { a: { a1: 'A1' }, c: 'C', d: {} }; diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index 1e08ad6cc2..6ab2dbeded 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -1,3 +1,5 @@ +import slugify from 'slugify'; + /** * 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 => { 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 +}