@contentful/field-editor-slug 3.0.1-canary.0 → 3.0.2-canary.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/SlugEditor.js +1 -14
- package/dist/cjs/SlugEditor.test.js +8 -33
- package/dist/cjs/SlugEditorField.js +7 -12
- package/dist/cjs/services/makeSlug.js +3 -3
- package/dist/cjs/services/makeSlug.test.js +0 -8
- package/dist/cjs/services/slugify.js +3 -3
- package/dist/cjs/services/slugify.test.js +0 -9
- package/dist/esm/SlugEditor.js +1 -14
- package/dist/esm/SlugEditor.test.js +8 -33
- package/dist/esm/SlugEditorField.js +7 -12
- package/dist/esm/services/makeSlug.js +3 -3
- package/dist/esm/services/makeSlug.test.js +0 -8
- package/dist/esm/services/slugify.js +3 -3
- package/dist/esm/services/slugify.test.js +0 -9
- package/dist/types/SlugEditorField.d.ts +0 -1
- package/dist/types/services/makeSlug.d.ts +0 -1
- package/dist/types/services/slugify.d.ts +2 -5
- package/package.json +4 -4
package/dist/cjs/SlugEditor.js
CHANGED
|
@@ -53,20 +53,10 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
53
53
|
}
|
|
54
54
|
return newObj;
|
|
55
55
|
}
|
|
56
|
-
const DEFAULT_SYMBOL_FIELD_MAX_LENGTH = 256;
|
|
57
|
-
function getSlugFieldMaxLength(validations = []) {
|
|
58
|
-
const maxFromValidations = validations.reduce((currentMax, validation)=>{
|
|
59
|
-
if (!('size' in validation) || typeof validation.size?.max !== 'number') {
|
|
60
|
-
return currentMax;
|
|
61
|
-
}
|
|
62
|
-
return currentMax === null ? validation.size.max : Math.min(currentMax, validation.size.max);
|
|
63
|
-
}, null);
|
|
64
|
-
return maxFromValidations === null ? DEFAULT_SYMBOL_FIELD_MAX_LENGTH : Math.min(DEFAULT_SYMBOL_FIELD_MAX_LENGTH, maxFromValidations);
|
|
65
|
-
}
|
|
66
56
|
function isSupportedFieldTypes(val) {
|
|
67
57
|
return val === 'Symbol';
|
|
68
58
|
}
|
|
69
|
-
function FieldConnectorCallback({ Component, value, disabled, setValue, errors, titleValue, isOptionalLocaleWithFallback, locale, createdAt,
|
|
59
|
+
function FieldConnectorCallback({ Component, value, disabled, setValue, errors, titleValue, isOptionalLocaleWithFallback, locale, createdAt, performUniqueCheck, isUniqueValidationEnabled, id }) {
|
|
70
60
|
const safeSetValue = _react.useCallback(async (...args)=>{
|
|
71
61
|
try {
|
|
72
62
|
await setValue(...args);
|
|
@@ -79,7 +69,6 @@ function FieldConnectorCallback({ Component, value, disabled, setValue, errors,
|
|
|
79
69
|
}, /*#__PURE__*/ _react.createElement(Component, {
|
|
80
70
|
locale: locale,
|
|
81
71
|
createdAt: createdAt,
|
|
82
|
-
maxLength: maxLength,
|
|
83
72
|
performUniqueCheck: performUniqueCheck,
|
|
84
73
|
isUniqueValidationEnabled: isUniqueValidationEnabled,
|
|
85
74
|
hasError: errors.length > 0,
|
|
@@ -100,7 +89,6 @@ function SlugEditor(props) {
|
|
|
100
89
|
const trackingFieldId = parameters?.instance?.trackingFieldId ?? undefined;
|
|
101
90
|
const entrySys = entry.getSys();
|
|
102
91
|
const isUniqueValidationEnabled = (field.validations || []).some((validation)=>'unique' in validation && validation.unique === true);
|
|
103
|
-
const maxLength = getSlugFieldMaxLength(field.validations);
|
|
104
92
|
const isLocaleOptional = locales.optional[field.locale];
|
|
105
93
|
const localeFallbackCode = locales.fallbacks[field.locale];
|
|
106
94
|
const isOptionalFieldLocale = Boolean(!field.required || isLocaleOptional);
|
|
@@ -148,7 +136,6 @@ function SlugEditor(props) {
|
|
|
148
136
|
isOptionalLocaleWithFallback: isOptionalLocaleWithFallback,
|
|
149
137
|
createdAt: entrySys.createdAt,
|
|
150
138
|
locale: field.locale,
|
|
151
|
-
maxLength: maxLength,
|
|
152
139
|
performUniqueCheck: performUniqueCheck,
|
|
153
140
|
isUniqueValidationEnabled: isUniqueValidationEnabled,
|
|
154
141
|
key: `slug-editor-${externalReset}`,
|
|
@@ -316,7 +316,6 @@ describe('SlugEditor', ()=>{
|
|
|
316
316
|
locale: "en-US",
|
|
317
317
|
titleValue: "Slug value",
|
|
318
318
|
createdAt: "2020-01-24T15:33:47.906Z",
|
|
319
|
-
maxLength: 256,
|
|
320
319
|
setValue: setValue,
|
|
321
320
|
performUniqueCheck: performUniqueCheck
|
|
322
321
|
}));
|
|
@@ -528,46 +527,22 @@ describe('SlugEditor', ()=>{
|
|
|
528
527
|
});
|
|
529
528
|
});
|
|
530
529
|
});
|
|
531
|
-
it('slug suggestion is limited to
|
|
532
|
-
const longTitle = 'a'.repeat(300);
|
|
530
|
+
it('slug suggestion is limited to 75 symbols', async ()=>{
|
|
533
531
|
const { field, sdk } = createMocks({
|
|
534
532
|
field: '',
|
|
535
|
-
titleField:
|
|
533
|
+
titleField: ''
|
|
536
534
|
});
|
|
537
|
-
|
|
535
|
+
(0, _react1.render)(/*#__PURE__*/ _react.createElement(_SlugEditor.SlugEditor, {
|
|
538
536
|
field: field,
|
|
539
537
|
baseSdk: sdk,
|
|
540
538
|
isInitiallyDisabled: false
|
|
541
539
|
}));
|
|
542
|
-
await (0, _react1.waitFor)(()=>{
|
|
543
|
-
|
|
544
|
-
expect(field.setValue).toHaveBeenLastCalledWith(expectedSlug);
|
|
545
|
-
expect(getByTestId('cf-ui-text-input')).toHaveAttribute('maxlength', '256');
|
|
546
|
-
});
|
|
547
|
-
});
|
|
548
|
-
it('slug suggestion respects size max validation', async ()=>{
|
|
549
|
-
const { field, sdk } = createMocks({
|
|
550
|
-
field: '',
|
|
551
|
-
titleField: 'one two three four'
|
|
540
|
+
await (0, _react1.waitFor)(async ()=>{
|
|
541
|
+
await sdk.entry.fields['title-id'].setValue('a'.repeat(80));
|
|
552
542
|
});
|
|
553
|
-
field.validations = [
|
|
554
|
-
{
|
|
555
|
-
unique: true
|
|
556
|
-
},
|
|
557
|
-
{
|
|
558
|
-
size: {
|
|
559
|
-
max: 13
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
];
|
|
563
|
-
const { getByTestId } = (0, _react1.render)(/*#__PURE__*/ _react.createElement(_SlugEditor.SlugEditor, {
|
|
564
|
-
field: field,
|
|
565
|
-
baseSdk: sdk,
|
|
566
|
-
isInitiallyDisabled: false
|
|
567
|
-
}));
|
|
568
543
|
await (0, _react1.waitFor)(()=>{
|
|
569
|
-
|
|
570
|
-
expect(
|
|
544
|
+
const expectedSlug = 'a'.repeat(75);
|
|
545
|
+
expect(field.setValue).toHaveBeenLastCalledWith(expectedSlug);
|
|
571
546
|
});
|
|
572
547
|
});
|
|
573
548
|
it('slug suggestion does not contain cut-off words', async ()=>{
|
|
@@ -581,7 +556,7 @@ describe('SlugEditor', ()=>{
|
|
|
581
556
|
isInitiallyDisabled: false
|
|
582
557
|
}));
|
|
583
558
|
await (0, _react1.waitFor)(async ()=>{
|
|
584
|
-
await sdk.entry.fields['title-id'].setValue(`one two three ${'a'.repeat(
|
|
559
|
+
await sdk.entry.fields['title-id'].setValue(`one two three ${'a'.repeat(80)}`);
|
|
585
560
|
});
|
|
586
561
|
await (0, _react1.waitFor)(()=>{
|
|
587
562
|
const expectedSlug = 'one-two-three';
|
|
@@ -66,7 +66,7 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
66
66
|
return newObj;
|
|
67
67
|
}
|
|
68
68
|
function useSlugUpdater(props, check) {
|
|
69
|
-
const { value, setValue, createdAt, locale, titleValue, isOptionalLocaleWithFallback
|
|
69
|
+
const { value, setValue, createdAt, locale, titleValue, isOptionalLocaleWithFallback } = props;
|
|
70
70
|
_react.useEffect(()=>{
|
|
71
71
|
if (check === false) {
|
|
72
72
|
return;
|
|
@@ -74,8 +74,7 @@ function useSlugUpdater(props, check) {
|
|
|
74
74
|
const newSlug = (0, _makeSlug.makeSlug)(titleValue, {
|
|
75
75
|
isOptionalLocaleWithFallback,
|
|
76
76
|
locale,
|
|
77
|
-
createdAt
|
|
78
|
-
maxLength
|
|
77
|
+
createdAt
|
|
79
78
|
});
|
|
80
79
|
if (newSlug !== value) {
|
|
81
80
|
setValue(newSlug);
|
|
@@ -87,7 +86,6 @@ function useSlugUpdater(props, check) {
|
|
|
87
86
|
check,
|
|
88
87
|
createdAt,
|
|
89
88
|
locale,
|
|
90
|
-
maxLength,
|
|
91
89
|
setValue
|
|
92
90
|
]);
|
|
93
91
|
}
|
|
@@ -113,7 +111,7 @@ function useUniqueChecker(props) {
|
|
|
113
111
|
return status;
|
|
114
112
|
}
|
|
115
113
|
function SlugEditorFieldStatic(props) {
|
|
116
|
-
const { hasError, isDisabled, value, setValue, onChange, onBlur, isUniqueValidationEnabled, id
|
|
114
|
+
const { hasError, isDisabled, value, setValue, onChange, onBlur, isUniqueValidationEnabled, id } = props;
|
|
117
115
|
const status = useUniqueChecker(props);
|
|
118
116
|
const hasDuplicate = status === 'duplicate';
|
|
119
117
|
const shouldShowDuplicateAsError = hasDuplicate && isUniqueValidationEnabled && !hasError;
|
|
@@ -128,7 +126,6 @@ function SlugEditorFieldStatic(props) {
|
|
|
128
126
|
isDisabled: isDisabled,
|
|
129
127
|
value: value || '',
|
|
130
128
|
id: id,
|
|
131
|
-
maxLength: maxLength,
|
|
132
129
|
onChange: (e)=>{
|
|
133
130
|
setValue(e.target.value);
|
|
134
131
|
if (onChange) {
|
|
@@ -160,13 +157,12 @@ function SlugEditorFieldStatic(props) {
|
|
|
160
157
|
})));
|
|
161
158
|
}
|
|
162
159
|
function SlugEditorField(props) {
|
|
163
|
-
const { titleValue, isOptionalLocaleWithFallback, locale, createdAt, value
|
|
160
|
+
const { titleValue, isOptionalLocaleWithFallback, locale, createdAt, value } = props;
|
|
164
161
|
const areEqual = _react.useCallback(()=>{
|
|
165
162
|
const potentialSlug = (0, _makeSlug.makeSlug)(titleValue, {
|
|
166
|
-
isOptionalLocaleWithFallback,
|
|
167
|
-
locale,
|
|
168
|
-
createdAt
|
|
169
|
-
maxLength
|
|
163
|
+
isOptionalLocaleWithFallback: isOptionalLocaleWithFallback,
|
|
164
|
+
locale: locale,
|
|
165
|
+
createdAt: createdAt
|
|
170
166
|
});
|
|
171
167
|
return value === potentialSlug;
|
|
172
168
|
}, [
|
|
@@ -174,7 +170,6 @@ function SlugEditorField(props) {
|
|
|
174
170
|
isOptionalLocaleWithFallback,
|
|
175
171
|
locale,
|
|
176
172
|
createdAt,
|
|
177
|
-
maxLength,
|
|
178
173
|
value
|
|
179
174
|
]);
|
|
180
175
|
const [check, setCheck] = _react.useState(()=>{
|
|
@@ -30,13 +30,13 @@ function formatUtcDate(date) {
|
|
|
30
30
|
const seconds = formatTwoDigit(date.getUTCSeconds());
|
|
31
31
|
return `${year} ${month} ${day} at ${hour} ${minutes} ${seconds}`;
|
|
32
32
|
}
|
|
33
|
-
function untitledSlug({ isOptionalLocaleWithFallback, createdAt
|
|
33
|
+
function untitledSlug({ isOptionalLocaleWithFallback, createdAt }) {
|
|
34
34
|
if (isOptionalLocaleWithFallback) {
|
|
35
35
|
return '';
|
|
36
36
|
}
|
|
37
37
|
const createdAtFormatted = formatUtcDate(new Date(createdAt));
|
|
38
|
-
return (0, _slugify.slugify)('Untitled entry ' + createdAtFormatted, 'en-US'
|
|
38
|
+
return (0, _slugify.slugify)('Untitled entry ' + createdAtFormatted, 'en-US');
|
|
39
39
|
}
|
|
40
40
|
function makeSlug(title, options) {
|
|
41
|
-
return title ? (0, _slugify.slugify)(title, options.locale
|
|
41
|
+
return title ? (0, _slugify.slugify)(title, options.locale) : untitledSlug(options);
|
|
42
42
|
}
|
|
@@ -11,12 +11,4 @@ describe('makeSlug', ()=>{
|
|
|
11
11
|
createdAt: '2020-01-14T14:45:39.709Z'
|
|
12
12
|
})).toBe('untitled-entry-2020-01-14-at-14-45-39');
|
|
13
13
|
});
|
|
14
|
-
it('should respect maxLength when title is present', ()=>{
|
|
15
|
-
expect((0, _makeSlug.makeSlug)('a'.repeat(300), {
|
|
16
|
-
locale: 'en',
|
|
17
|
-
isOptionalLocaleWithFallback: false,
|
|
18
|
-
createdAt: '2020-01-14T14:45:39.709Z',
|
|
19
|
-
maxLength: 256
|
|
20
|
-
})).toBe('a'.repeat(256));
|
|
21
|
-
});
|
|
22
14
|
});
|
|
@@ -14,7 +14,7 @@ function _interop_require_default(obj) {
|
|
|
14
14
|
default: obj
|
|
15
15
|
};
|
|
16
16
|
}
|
|
17
|
-
const
|
|
17
|
+
const CF_GENERATED_SLUG_MAX_LENGTH = 75;
|
|
18
18
|
const languages = [
|
|
19
19
|
'ar',
|
|
20
20
|
'az',
|
|
@@ -49,11 +49,11 @@ function supportedLanguage(locale) {
|
|
|
49
49
|
const prefix = locale.slice(0, 2).toLowerCase();
|
|
50
50
|
return languages[languages.indexOf(prefix)];
|
|
51
51
|
}
|
|
52
|
-
function slugify(text, locale = 'en'
|
|
52
|
+
function slugify(text, locale = 'en') {
|
|
53
53
|
return (0, _speakingurl.default)(text, {
|
|
54
54
|
separator: '-',
|
|
55
55
|
lang: supportedLanguage(locale) || 'en',
|
|
56
|
-
truncate:
|
|
56
|
+
truncate: CF_GENERATED_SLUG_MAX_LENGTH + 1,
|
|
57
57
|
custom: {
|
|
58
58
|
"'": '',
|
|
59
59
|
'`': '',
|
|
@@ -27,13 +27,4 @@ describe('slugify', ()=>{
|
|
|
27
27
|
expect((0, _slugify.slugify)(input[0])).toBe(input[1]);
|
|
28
28
|
});
|
|
29
29
|
});
|
|
30
|
-
it('defaults to a 75 character limit', ()=>{
|
|
31
|
-
expect((0, _slugify.slugify)('a'.repeat(80))).toBe('a'.repeat(75));
|
|
32
|
-
});
|
|
33
|
-
it('accepts a custom max length', ()=>{
|
|
34
|
-
expect((0, _slugify.slugify)('a'.repeat(80), 'en', 80)).toBe('a'.repeat(80));
|
|
35
|
-
});
|
|
36
|
-
it('does not cut off words when a custom max length is provided', ()=>{
|
|
37
|
-
expect((0, _slugify.slugify)('one two three four', 'en', 13)).toBe('one-two-three');
|
|
38
|
-
});
|
|
39
30
|
});
|
package/dist/esm/SlugEditor.js
CHANGED
|
@@ -2,20 +2,10 @@ import * as React from 'react';
|
|
|
2
2
|
import { FieldConnector } from '@contentful/field-editor-shared';
|
|
3
3
|
import { SlugEditorField, SlugEditorFieldStatic } from './SlugEditorField';
|
|
4
4
|
import { TrackingFieldConnector } from './TrackingFieldConnector';
|
|
5
|
-
const DEFAULT_SYMBOL_FIELD_MAX_LENGTH = 256;
|
|
6
|
-
function getSlugFieldMaxLength(validations = []) {
|
|
7
|
-
const maxFromValidations = validations.reduce((currentMax, validation)=>{
|
|
8
|
-
if (!('size' in validation) || typeof validation.size?.max !== 'number') {
|
|
9
|
-
return currentMax;
|
|
10
|
-
}
|
|
11
|
-
return currentMax === null ? validation.size.max : Math.min(currentMax, validation.size.max);
|
|
12
|
-
}, null);
|
|
13
|
-
return maxFromValidations === null ? DEFAULT_SYMBOL_FIELD_MAX_LENGTH : Math.min(DEFAULT_SYMBOL_FIELD_MAX_LENGTH, maxFromValidations);
|
|
14
|
-
}
|
|
15
5
|
function isSupportedFieldTypes(val) {
|
|
16
6
|
return val === 'Symbol';
|
|
17
7
|
}
|
|
18
|
-
function FieldConnectorCallback({ Component, value, disabled, setValue, errors, titleValue, isOptionalLocaleWithFallback, locale, createdAt,
|
|
8
|
+
function FieldConnectorCallback({ Component, value, disabled, setValue, errors, titleValue, isOptionalLocaleWithFallback, locale, createdAt, performUniqueCheck, isUniqueValidationEnabled, id }) {
|
|
19
9
|
const safeSetValue = React.useCallback(async (...args)=>{
|
|
20
10
|
try {
|
|
21
11
|
await setValue(...args);
|
|
@@ -28,7 +18,6 @@ function FieldConnectorCallback({ Component, value, disabled, setValue, errors,
|
|
|
28
18
|
}, /*#__PURE__*/ React.createElement(Component, {
|
|
29
19
|
locale: locale,
|
|
30
20
|
createdAt: createdAt,
|
|
31
|
-
maxLength: maxLength,
|
|
32
21
|
performUniqueCheck: performUniqueCheck,
|
|
33
22
|
isUniqueValidationEnabled: isUniqueValidationEnabled,
|
|
34
23
|
hasError: errors.length > 0,
|
|
@@ -49,7 +38,6 @@ export function SlugEditor(props) {
|
|
|
49
38
|
const trackingFieldId = parameters?.instance?.trackingFieldId ?? undefined;
|
|
50
39
|
const entrySys = entry.getSys();
|
|
51
40
|
const isUniqueValidationEnabled = (field.validations || []).some((validation)=>'unique' in validation && validation.unique === true);
|
|
52
|
-
const maxLength = getSlugFieldMaxLength(field.validations);
|
|
53
41
|
const isLocaleOptional = locales.optional[field.locale];
|
|
54
42
|
const localeFallbackCode = locales.fallbacks[field.locale];
|
|
55
43
|
const isOptionalFieldLocale = Boolean(!field.required || isLocaleOptional);
|
|
@@ -97,7 +85,6 @@ export function SlugEditor(props) {
|
|
|
97
85
|
isOptionalLocaleWithFallback: isOptionalLocaleWithFallback,
|
|
98
86
|
createdAt: entrySys.createdAt,
|
|
99
87
|
locale: field.locale,
|
|
100
|
-
maxLength: maxLength,
|
|
101
88
|
performUniqueCheck: performUniqueCheck,
|
|
102
89
|
isUniqueValidationEnabled: isUniqueValidationEnabled,
|
|
103
90
|
key: `slug-editor-${externalReset}`,
|
|
@@ -271,7 +271,6 @@ describe('SlugEditor', ()=>{
|
|
|
271
271
|
locale: "en-US",
|
|
272
272
|
titleValue: "Slug value",
|
|
273
273
|
createdAt: "2020-01-24T15:33:47.906Z",
|
|
274
|
-
maxLength: 256,
|
|
275
274
|
setValue: setValue,
|
|
276
275
|
performUniqueCheck: performUniqueCheck
|
|
277
276
|
}));
|
|
@@ -483,46 +482,22 @@ describe('SlugEditor', ()=>{
|
|
|
483
482
|
});
|
|
484
483
|
});
|
|
485
484
|
});
|
|
486
|
-
it('slug suggestion is limited to
|
|
487
|
-
const longTitle = 'a'.repeat(300);
|
|
485
|
+
it('slug suggestion is limited to 75 symbols', async ()=>{
|
|
488
486
|
const { field, sdk } = createMocks({
|
|
489
487
|
field: '',
|
|
490
|
-
titleField:
|
|
488
|
+
titleField: ''
|
|
491
489
|
});
|
|
492
|
-
|
|
490
|
+
render(/*#__PURE__*/ React.createElement(SlugEditor, {
|
|
493
491
|
field: field,
|
|
494
492
|
baseSdk: sdk,
|
|
495
493
|
isInitiallyDisabled: false
|
|
496
494
|
}));
|
|
497
|
-
await waitFor(()=>{
|
|
498
|
-
|
|
499
|
-
expect(field.setValue).toHaveBeenLastCalledWith(expectedSlug);
|
|
500
|
-
expect(getByTestId('cf-ui-text-input')).toHaveAttribute('maxlength', '256');
|
|
501
|
-
});
|
|
502
|
-
});
|
|
503
|
-
it('slug suggestion respects size max validation', async ()=>{
|
|
504
|
-
const { field, sdk } = createMocks({
|
|
505
|
-
field: '',
|
|
506
|
-
titleField: 'one two three four'
|
|
495
|
+
await waitFor(async ()=>{
|
|
496
|
+
await sdk.entry.fields['title-id'].setValue('a'.repeat(80));
|
|
507
497
|
});
|
|
508
|
-
field.validations = [
|
|
509
|
-
{
|
|
510
|
-
unique: true
|
|
511
|
-
},
|
|
512
|
-
{
|
|
513
|
-
size: {
|
|
514
|
-
max: 13
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
];
|
|
518
|
-
const { getByTestId } = render(/*#__PURE__*/ React.createElement(SlugEditor, {
|
|
519
|
-
field: field,
|
|
520
|
-
baseSdk: sdk,
|
|
521
|
-
isInitiallyDisabled: false
|
|
522
|
-
}));
|
|
523
498
|
await waitFor(()=>{
|
|
524
|
-
|
|
525
|
-
expect(
|
|
499
|
+
const expectedSlug = 'a'.repeat(75);
|
|
500
|
+
expect(field.setValue).toHaveBeenLastCalledWith(expectedSlug);
|
|
526
501
|
});
|
|
527
502
|
});
|
|
528
503
|
it('slug suggestion does not contain cut-off words', async ()=>{
|
|
@@ -536,7 +511,7 @@ describe('SlugEditor', ()=>{
|
|
|
536
511
|
isInitiallyDisabled: false
|
|
537
512
|
}));
|
|
538
513
|
await waitFor(async ()=>{
|
|
539
|
-
await sdk.entry.fields['title-id'].setValue(`one two three ${'a'.repeat(
|
|
514
|
+
await sdk.entry.fields['title-id'].setValue(`one two three ${'a'.repeat(80)}`);
|
|
540
515
|
});
|
|
541
516
|
await waitFor(()=>{
|
|
542
517
|
const expectedSlug = 'one-two-three';
|
|
@@ -7,7 +7,7 @@ import { useDebounce } from 'use-debounce';
|
|
|
7
7
|
import { makeSlug } from './services/makeSlug';
|
|
8
8
|
import * as styles from './styles';
|
|
9
9
|
function useSlugUpdater(props, check) {
|
|
10
|
-
const { value, setValue, createdAt, locale, titleValue, isOptionalLocaleWithFallback
|
|
10
|
+
const { value, setValue, createdAt, locale, titleValue, isOptionalLocaleWithFallback } = props;
|
|
11
11
|
React.useEffect(()=>{
|
|
12
12
|
if (check === false) {
|
|
13
13
|
return;
|
|
@@ -15,8 +15,7 @@ function useSlugUpdater(props, check) {
|
|
|
15
15
|
const newSlug = makeSlug(titleValue, {
|
|
16
16
|
isOptionalLocaleWithFallback,
|
|
17
17
|
locale,
|
|
18
|
-
createdAt
|
|
19
|
-
maxLength
|
|
18
|
+
createdAt
|
|
20
19
|
});
|
|
21
20
|
if (newSlug !== value) {
|
|
22
21
|
setValue(newSlug);
|
|
@@ -28,7 +27,6 @@ function useSlugUpdater(props, check) {
|
|
|
28
27
|
check,
|
|
29
28
|
createdAt,
|
|
30
29
|
locale,
|
|
31
|
-
maxLength,
|
|
32
30
|
setValue
|
|
33
31
|
]);
|
|
34
32
|
}
|
|
@@ -54,7 +52,7 @@ function useUniqueChecker(props) {
|
|
|
54
52
|
return status;
|
|
55
53
|
}
|
|
56
54
|
export function SlugEditorFieldStatic(props) {
|
|
57
|
-
const { hasError, isDisabled, value, setValue, onChange, onBlur, isUniqueValidationEnabled, id
|
|
55
|
+
const { hasError, isDisabled, value, setValue, onChange, onBlur, isUniqueValidationEnabled, id } = props;
|
|
58
56
|
const status = useUniqueChecker(props);
|
|
59
57
|
const hasDuplicate = status === 'duplicate';
|
|
60
58
|
const shouldShowDuplicateAsError = hasDuplicate && isUniqueValidationEnabled && !hasError;
|
|
@@ -69,7 +67,6 @@ export function SlugEditorFieldStatic(props) {
|
|
|
69
67
|
isDisabled: isDisabled,
|
|
70
68
|
value: value || '',
|
|
71
69
|
id: id,
|
|
72
|
-
maxLength: maxLength,
|
|
73
70
|
onChange: (e)=>{
|
|
74
71
|
setValue(e.target.value);
|
|
75
72
|
if (onChange) {
|
|
@@ -101,13 +98,12 @@ export function SlugEditorFieldStatic(props) {
|
|
|
101
98
|
})));
|
|
102
99
|
}
|
|
103
100
|
export function SlugEditorField(props) {
|
|
104
|
-
const { titleValue, isOptionalLocaleWithFallback, locale, createdAt, value
|
|
101
|
+
const { titleValue, isOptionalLocaleWithFallback, locale, createdAt, value } = props;
|
|
105
102
|
const areEqual = React.useCallback(()=>{
|
|
106
103
|
const potentialSlug = makeSlug(titleValue, {
|
|
107
|
-
isOptionalLocaleWithFallback,
|
|
108
|
-
locale,
|
|
109
|
-
createdAt
|
|
110
|
-
maxLength
|
|
104
|
+
isOptionalLocaleWithFallback: isOptionalLocaleWithFallback,
|
|
105
|
+
locale: locale,
|
|
106
|
+
createdAt: createdAt
|
|
111
107
|
});
|
|
112
108
|
return value === potentialSlug;
|
|
113
109
|
}, [
|
|
@@ -115,7 +111,6 @@ export function SlugEditorField(props) {
|
|
|
115
111
|
isOptionalLocaleWithFallback,
|
|
116
112
|
locale,
|
|
117
113
|
createdAt,
|
|
118
|
-
maxLength,
|
|
119
114
|
value
|
|
120
115
|
]);
|
|
121
116
|
const [check, setCheck] = React.useState(()=>{
|
|
@@ -12,13 +12,13 @@ export function formatUtcDate(date) {
|
|
|
12
12
|
const seconds = formatTwoDigit(date.getUTCSeconds());
|
|
13
13
|
return `${year} ${month} ${day} at ${hour} ${minutes} ${seconds}`;
|
|
14
14
|
}
|
|
15
|
-
function untitledSlug({ isOptionalLocaleWithFallback, createdAt
|
|
15
|
+
function untitledSlug({ isOptionalLocaleWithFallback, createdAt }) {
|
|
16
16
|
if (isOptionalLocaleWithFallback) {
|
|
17
17
|
return '';
|
|
18
18
|
}
|
|
19
19
|
const createdAtFormatted = formatUtcDate(new Date(createdAt));
|
|
20
|
-
return slugify('Untitled entry ' + createdAtFormatted, 'en-US'
|
|
20
|
+
return slugify('Untitled entry ' + createdAtFormatted, 'en-US');
|
|
21
21
|
}
|
|
22
22
|
export function makeSlug(title, options) {
|
|
23
|
-
return title ? slugify(title, options.locale
|
|
23
|
+
return title ? slugify(title, options.locale) : untitledSlug(options);
|
|
24
24
|
}
|
|
@@ -7,12 +7,4 @@ describe('makeSlug', ()=>{
|
|
|
7
7
|
createdAt: '2020-01-14T14:45:39.709Z'
|
|
8
8
|
})).toBe('untitled-entry-2020-01-14-at-14-45-39');
|
|
9
9
|
});
|
|
10
|
-
it('should respect maxLength when title is present', ()=>{
|
|
11
|
-
expect(makeSlug('a'.repeat(300), {
|
|
12
|
-
locale: 'en',
|
|
13
|
-
isOptionalLocaleWithFallback: false,
|
|
14
|
-
createdAt: '2020-01-14T14:45:39.709Z',
|
|
15
|
-
maxLength: 256
|
|
16
|
-
})).toBe('a'.repeat(256));
|
|
17
|
-
});
|
|
18
10
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import getSlug from 'speakingurl';
|
|
2
|
-
const
|
|
2
|
+
const CF_GENERATED_SLUG_MAX_LENGTH = 75;
|
|
3
3
|
const languages = [
|
|
4
4
|
'ar',
|
|
5
5
|
'az',
|
|
@@ -34,11 +34,11 @@ function supportedLanguage(locale) {
|
|
|
34
34
|
const prefix = locale.slice(0, 2).toLowerCase();
|
|
35
35
|
return languages[languages.indexOf(prefix)];
|
|
36
36
|
}
|
|
37
|
-
export function slugify(text, locale = 'en'
|
|
37
|
+
export function slugify(text, locale = 'en') {
|
|
38
38
|
return getSlug(text, {
|
|
39
39
|
separator: '-',
|
|
40
40
|
lang: supportedLanguage(locale) || 'en',
|
|
41
|
-
truncate:
|
|
41
|
+
truncate: CF_GENERATED_SLUG_MAX_LENGTH + 1,
|
|
42
42
|
custom: {
|
|
43
43
|
"'": '',
|
|
44
44
|
'`': '',
|
|
@@ -23,13 +23,4 @@ describe('slugify', ()=>{
|
|
|
23
23
|
expect(slugify(input[0])).toBe(input[1]);
|
|
24
24
|
});
|
|
25
25
|
});
|
|
26
|
-
it('defaults to a 75 character limit', ()=>{
|
|
27
|
-
expect(slugify('a'.repeat(80))).toBe('a'.repeat(75));
|
|
28
|
-
});
|
|
29
|
-
it('accepts a custom max length', ()=>{
|
|
30
|
-
expect(slugify('a'.repeat(80), 'en', 80)).toBe('a'.repeat(80));
|
|
31
|
-
});
|
|
32
|
-
it('does not cut off words when a custom max length is provided', ()=>{
|
|
33
|
-
expect(slugify('one two three four', 'en', 13)).toBe('one-two-three');
|
|
34
|
-
});
|
|
35
26
|
});
|
|
@@ -8,7 +8,6 @@ interface SlugEditorFieldProps {
|
|
|
8
8
|
locale: string;
|
|
9
9
|
titleValue: string | null | undefined;
|
|
10
10
|
createdAt: string;
|
|
11
|
-
maxLength: number;
|
|
12
11
|
setValue: (value: string | null | undefined) => void;
|
|
13
12
|
performUniqueCheck: (value: string) => Promise<boolean>;
|
|
14
13
|
id?: string;
|
|
@@ -2,7 +2,6 @@ type MakeSlugOptions = {
|
|
|
2
2
|
locale: string;
|
|
3
3
|
isOptionalLocaleWithFallback: boolean;
|
|
4
4
|
createdAt: string;
|
|
5
|
-
maxLength?: number;
|
|
6
5
|
};
|
|
7
6
|
export declare function formatUtcDate(date: Date): string;
|
|
8
7
|
export declare function makeSlug(title: string | null | undefined, options: MakeSlugOptions): string;
|
|
@@ -3,13 +3,10 @@
|
|
|
3
3
|
* If the locale belongs to a language supported by SpeakingURL, it
|
|
4
4
|
* is used as the symbol language. Otherwise, the symbol language
|
|
5
5
|
* is english.
|
|
6
|
-
*
|
|
7
|
-
* By default slug suggestions are limited to 75 characters.
|
|
8
|
-
* Consumers can override that limit via maxLength.
|
|
6
|
+
* Slug suggestions are limited to 75 characters.
|
|
9
7
|
*
|
|
10
8
|
* @param {string} text To be turned into a slug.
|
|
11
9
|
* @param {string?} locale
|
|
12
|
-
* @param {number?} maxLength
|
|
13
10
|
* @returns {string} Slug for provided text.
|
|
14
11
|
*/
|
|
15
|
-
export declare function slugify(text: string, locale?: string
|
|
12
|
+
export declare function slugify(text: string, locale?: string): string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentful/field-editor-slug",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.2-canary.9+78e1d2c5",
|
|
4
4
|
"main": "dist/cjs/index.js",
|
|
5
5
|
"module": "dist/esm/index.js",
|
|
6
6
|
"types": "dist/types/index.d.ts",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"@contentful/f36-icons": "^6.7.1",
|
|
41
41
|
"@contentful/f36-note": "^6.7.0",
|
|
42
42
|
"@contentful/f36-tokens": "^6.1.2",
|
|
43
|
-
"@contentful/field-editor-shared": "^3.0.
|
|
43
|
+
"@contentful/field-editor-shared": "^3.0.2-canary.9+78e1d2c5",
|
|
44
44
|
"@emotion/css": "^11.13.5",
|
|
45
45
|
"@types/speakingurl": "^13.0.2",
|
|
46
46
|
"speakingurl": "^14.0.1",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@contentful/app-sdk": "^4.45.0",
|
|
51
|
-
"@contentful/field-editor-test-utils": "^
|
|
51
|
+
"@contentful/field-editor-test-utils": "^2.0.0",
|
|
52
52
|
"@lingui/core": "5.3.0"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"publishConfig": {
|
|
60
60
|
"registry": "https://npm.pkg.github.com/"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "78e1d2c5e559a6db26a47ce2ddb109a8eb985715"
|
|
63
63
|
}
|