diff --git a/README.md b/README.md index 188b6258f1..8d4dbb27e8 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@

- NPM Version + NPM Version Monthly download on NPM diff --git a/docs/v3.x/concepts/models.md b/docs/v3.x/concepts/models.md index 9db353f219..61ac0b311c 100644 --- a/docs/v3.x/concepts/models.md +++ b/docs/v3.x/concepts/models.md @@ -215,7 +215,10 @@ To improve the Developer Experience when developing or using the administration ### Exceptions -- `uid` — This field type allows a `targetField` key. The value is the name of an attribute thas has `string` of `text` type. +**uid** + +- `targetField`(string) — The value is the name of an attribute thas has `string` of `text` type. +- `options` (string) — The value is a set of options passed to [the underlying `uid` generator](https://github.com/sindresorhus/slugify). A caveat is that the resulting `uid` must abide to the following RegEx `/^[A-Za-z0-9-_.~]*$`. ### Example diff --git a/packages/strapi-plugin-content-manager/services/__tests__/uid.test.js b/packages/strapi-plugin-content-manager/services/__tests__/uid.test.js index 5b02522350..e4d5f4a2e6 100644 --- a/packages/strapi-plugin-content-manager/services/__tests__/uid.test.js +++ b/packages/strapi-plugin-content-manager/services/__tests__/uid.test.js @@ -132,6 +132,43 @@ describe('Test uid service', () => { expect(uidWithEmptyTarget).toBe('my-test-model'); }); + test('Uses options for generation', async () => { + global.strapi = { + contentTypes: { + 'my-model': { + modelName: 'myTestModel', + attributes: { + title: { + type: 'string', + }, + slug: { + type: 'uid', + targetField: 'title', + options: { lowercase: false }, + }, + }, + }, + }, + db: { + query() { + return { + find: async () => [], + }; + }, + }, + }; + + const uid = await uidService.generateUIDField({ + contentTypeUID: 'my-model', + field: 'slug', + data: { + title: 'Test title', + }, + }); + + expect(uid).toBe('Test-title'); + }); + test('Ignores minLength attribute (should be handle by the user)', async () => { global.strapi = { contentTypes: { diff --git a/packages/strapi-plugin-content-manager/services/uid.js b/packages/strapi-plugin-content-manager/services/uid.js index 5883e9539d..7e5cd8eeee 100644 --- a/packages/strapi-plugin-content-manager/services/uid.js +++ b/packages/strapi-plugin-content-manager/services/uid.js @@ -8,21 +8,21 @@ module.exports = { const contentType = strapi.contentTypes[contentTypeUID]; const { attributes } = contentType; - const { targetField, default: defaultValue } = attributes[field]; + const { targetField, default: defaultValue, options } = attributes[field]; const targetValue = _.get(data, targetField); if (!_.isEmpty(targetValue)) { return this.findUniqueUID({ contentTypeUID, field, - value: slugify(targetValue), + value: slugify(targetValue, options), }); } return this.findUniqueUID({ contentTypeUID, field, - value: slugify(defaultValue || contentType.modelName), + value: slugify(defaultValue || contentType.modelName, options), }); }, diff --git a/packages/strapi-plugin-content-type-builder/controllers/validation/types.js b/packages/strapi-plugin-content-type-builder/controllers/validation/types.js index 8460ff2669..fc02bca86d 100644 --- a/packages/strapi-plugin-content-type-builder/controllers/validation/types.js +++ b/packages/strapi-plugin-content-type-builder/controllers/validation/types.js @@ -86,6 +86,19 @@ const getTypeShape = (attribute, { modelType, attributes } = {}) => { .test(isValidUID), minLength: validators.minLength, maxLength: validators.maxLength.max(256).test(maxLengthIsGreaterThanOrEqualToMinLength), + options: yup.object().shape({ + separator: yup.string(), + lowercase: yup.boolean(), + decamelize: yup.boolean(), + customReplacements: yup.array().of( + yup + .array() + .of(yup.string()) + .min(2) + .max(2) + ), + preserveLeadingUnderscore: yup.boolean(), + }), }; }