diff --git a/README.md b/README.md index 188b6258f1..8d4dbb27e8 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@
-
+
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(),
+ }),
};
}