Skip to content

Commit b678203

Browse files
author
Roehl, Johann (extern)
committed
feat: add max-slug-length property to instance paramaters
1 parent 3615641 commit b678203

File tree

5 files changed

+42
-19
lines changed

5 files changed

+42
-19
lines changed

packages/slug/src/SlugEditor.test.tsx

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import identity from 'lodash/identity';
33
import { render, configure, cleanup, wait, fireEvent } from '@testing-library/react';
44
import '@testing-library/jest-dom/extend-expect';
55
import { SlugEditor } from './SlugEditor';
6+
import { CF_GENERATED_SLUG_MAX_LENGTH } from './services/slugify';
67
import { createFakeFieldAPI, createFakeLocalesAPI } from '@contentful/field-editor-test-utils';
78

89
configure({
@@ -453,21 +454,34 @@ describe('SlugEditor', () => {
453454
});
454455
});
455456

456-
it('slug suggestion is limited to 75 symbols', async () => {
457-
const { field, sdk } = createMocks({
458-
field: '',
459-
titleField: '',
460-
});
457+
[undefined, 0, 100].forEach((maxSlugLength) => {
458+
it(`slug suggestion is limited to ${
459+
maxSlugLength || `${CF_GENERATED_SLUG_MAX_LENGTH} (default)`
460+
} symbols`, async () => {
461+
const { field, sdk } = createMocks({
462+
field: '',
463+
titleField: '',
464+
});
461465

462-
render(<SlugEditor field={field} baseSdk={sdk as any} isInitiallyDisabled={false} />);
466+
render(
467+
<SlugEditor
468+
field={field}
469+
baseSdk={sdk as any}
470+
isInitiallyDisabled={false}
471+
parameters={{ instance: { maxSlugLength } }}
472+
/>
473+
);
463474

464-
await wait();
475+
await wait();
465476

466-
await sdk.entry.fields['title-id'].setValue('a'.repeat(80));
467-
await wait();
477+
await sdk.entry.fields['title-id'].setValue(
478+
'a'.repeat((maxSlugLength ?? CF_GENERATED_SLUG_MAX_LENGTH) + 10)
479+
);
480+
await wait();
468481

469-
const expectedSlug = 'a'.repeat(75);
470-
expect(field.setValue).toHaveBeenLastCalledWith(expectedSlug);
482+
const expectedSlug = 'a'.repeat(maxSlugLength ?? CF_GENERATED_SLUG_MAX_LENGTH);
483+
expect(field.setValue).toHaveBeenLastCalledWith(expectedSlug);
484+
});
471485
});
472486

473487
it('slug suggestion does not contain cut-off words', async () => {

packages/slug/src/SlugEditor.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export interface SlugEditorProps {
2020
parameters?: {
2121
instance: {
2222
trackingFieldId?: string;
23+
maxSlugLength?: number;
2324
};
2425
};
2526
}
@@ -50,6 +51,7 @@ function FieldConnectorCallback({
5051
locale: FieldAPI['locale'];
5152
createdAt: string;
5253
performUniqueCheck: (value: string) => Promise<boolean>;
54+
maxSlugLength?: number;
5355
}) {
5456
// it is needed to silent permission errors
5557
// this happens when setValue is called on a field which is disabled for permission reasons
@@ -90,6 +92,7 @@ export function SlugEditor(props: SlugEditorProps) {
9092
}
9193

9294
const trackingFieldId = parameters?.instance?.trackingFieldId ?? undefined;
95+
const maxSlugLength = parameters?.instance?.maxSlugLength ?? undefined;
9396
const entrySys = entry.getSys();
9497

9598
const isLocaleOptional = locales.optional[field.locale];
@@ -149,6 +152,7 @@ export function SlugEditor(props: SlugEditorProps) {
149152
createdAt={entrySys.createdAt}
150153
locale={field.locale}
151154
performUniqueCheck={performUniqueCheck}
155+
maxSlugLength={maxSlugLength}
152156
key={`slug-editor-${externalReset}`}
153157
/>
154158
);

packages/slug/src/SlugEditorField.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@ interface SlugEditorFieldProps {
1717
createdAt: string;
1818
setValue: (value: string | null | undefined) => void;
1919
performUniqueCheck: (value: string) => Promise<boolean>;
20+
maxSlugLength?: number;
2021
}
2122

2223
type CheckerState = 'checking' | 'unique' | 'duplicate';
2324

2425
function useSlugUpdater(props: SlugEditorFieldProps, check: boolean) {
25-
const { value, setValue, createdAt, locale, titleValue, isOptionalLocaleWithFallback } = props;
26+
const { value, setValue, createdAt, locale, titleValue, isOptionalLocaleWithFallback, maxSlugLength } = props;
2627

2728
React.useEffect(() => {
2829
if (check === false) {
@@ -32,11 +33,12 @@ function useSlugUpdater(props: SlugEditorFieldProps, check: boolean) {
3233
isOptionalLocaleWithFallback,
3334
locale,
3435
createdAt,
36+
maxSlugLength
3537
});
3638
if (newSlug !== value) {
3739
setValue(newSlug);
3840
}
39-
}, [value, titleValue, isOptionalLocaleWithFallback, check, createdAt, locale, setValue]);
41+
}, [value, titleValue, isOptionalLocaleWithFallback, check, createdAt, locale, setValue, maxSlugLength]);
4042
}
4143

4244
function useUniqueChecker(props: SlugEditorFieldProps) {
@@ -111,16 +113,17 @@ export function SlugEditorFieldStatic(
111113
}
112114

113115
export function SlugEditorField(props: SlugEditorFieldProps) {
114-
const { titleValue, isOptionalLocaleWithFallback, locale, createdAt, value } = props;
116+
const { titleValue, isOptionalLocaleWithFallback, locale, createdAt, value, maxSlugLength } = props;
115117

116118
const areEqual = React.useCallback(() => {
117119
const potentialSlug = makeSlug(titleValue, {
118120
isOptionalLocaleWithFallback: isOptionalLocaleWithFallback,
119121
locale: locale,
120122
createdAt: createdAt,
123+
maxSlugLength
121124
});
122125
return value === potentialSlug;
123-
}, [titleValue, isOptionalLocaleWithFallback, locale, createdAt, value]);
126+
}, [titleValue, isOptionalLocaleWithFallback, locale, createdAt, value, maxSlugLength]);
124127

125128
const [check, setCheck] = React.useState<boolean>(() => {
126129
if (props.value) {

packages/slug/src/services/makeSlug.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ type MakeSlugOptions = {
44
locale: string;
55
isOptionalLocaleWithFallback: boolean;
66
createdAt: string;
7+
maxSlugLength?: number;
78
};
89

910
function formatTwoDigit(num: number) {
@@ -32,5 +33,5 @@ function untitledSlug({ isOptionalLocaleWithFallback, createdAt }: MakeSlugOptio
3233
}
3334

3435
export function makeSlug(title: string | null | undefined, options: MakeSlugOptions) {
35-
return title ? slugify(title, options.locale) : untitledSlug(options);
36+
return title ? slugify(title, options.locale, options.maxSlugLength) : untitledSlug(options);
3637
}

packages/slug/src/services/slugify.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import getSlug from 'speakingurl';
22

3-
const CF_GENERATED_SLUG_MAX_LENGTH = 75;
3+
export const CF_GENERATED_SLUG_MAX_LENGTH = 75;
44

55
const languages = [
66
'ar',
@@ -51,13 +51,14 @@ function supportedLanguage(locale: string) {
5151
*
5252
* @param {string} text To be turned into a slug.
5353
* @param {string?} locale
54+
* @param {number?} maxLength
5455
* @returns {string} Slug for provided text.
5556
*/
56-
export function slugify(text: string, locale = 'en') {
57+
export function slugify(text: string, locale = 'en', maxLength = CF_GENERATED_SLUG_MAX_LENGTH) {
5758
return getSlug(text, {
5859
separator: '-',
5960
lang: supportedLanguage(locale) || 'en',
60-
truncate: CF_GENERATED_SLUG_MAX_LENGTH + 1,
61+
truncate: maxLength + 1,
6162
custom: {
6263
"'": '',
6364
'`': '',

0 commit comments

Comments
 (0)