mirror of
https://github.com/ComfortablyCoding/strapi-plugin-slugify.git
synced 2025-07-05 00:01:10 -04:00
Compare commits
2 Commits
ccb31f7389
...
2d53829e94
Author | SHA1 | Date | |
---|---|---|---|
|
2d53829e94 | ||
|
9c336ebb1d |
@ -47,7 +47,7 @@
|
|||||||
"kind": "plugin"
|
"kind": "plugin"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12.x.x <=16.x.x",
|
"node": ">=14.19.1 <=18.x.x",
|
||||||
"npm": ">=6.0.0"
|
"npm": ">=6.0.0"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
@ -2,8 +2,15 @@
|
|||||||
|
|
||||||
const { buildSettings } = require('./buildSettings');
|
const { buildSettings } = require('./buildSettings');
|
||||||
const { setupLifecycles } = require('./setupLifecycles');
|
const { setupLifecycles } = require('./setupLifecycles');
|
||||||
|
const { syncSlugCount } = require('./syncSlugCount');
|
||||||
|
|
||||||
|
module.exports = async () => {
|
||||||
|
const settings = await buildSettings();
|
||||||
|
|
||||||
|
if (settings.slugifyWithCount) {
|
||||||
|
// Ensure correct count used for old plugin versions and projects with existing slugs.
|
||||||
|
await syncSlugCount(settings);
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = async ({ strapi }) => {
|
|
||||||
const settings = await buildSettings(strapi);
|
|
||||||
setupLifecycles(settings);
|
setupLifecycles(settings);
|
||||||
};
|
};
|
||||||
|
75
server/bootstrap/syncSlugCount.js
Normal file
75
server/bootstrap/syncSlugCount.js
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const syncSlugCount = async (settings) => {
|
||||||
|
const entries = await strapi.entityService.findMany('plugin::slugify.slug', {
|
||||||
|
filters: { createdAt: { $gt: 1 } },
|
||||||
|
});
|
||||||
|
|
||||||
|
// if entries aready present we can skip sync
|
||||||
|
if (entries && entries.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
strapi.log.info('[slugify] syncing slug count for registered content types');
|
||||||
|
|
||||||
|
const slugs = new Map();
|
||||||
|
|
||||||
|
// chec slugs in each reigistered model
|
||||||
|
for (const uid in settings.modelsByUID) {
|
||||||
|
if (!Object.hasOwnProperty.call(settings.modelsByUID, uid)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const model = settings.modelsByUID[uid];
|
||||||
|
|
||||||
|
// using db query to avoid the need to check if CT has draftAndPublish enabled
|
||||||
|
const modelEntries = await strapi.db.query(model.uid).findMany({
|
||||||
|
filters: { createdAt: { $gt: 1 } },
|
||||||
|
});
|
||||||
|
|
||||||
|
strapi.log.info(`[slugify] syncing slug count for ${model.uid}`);
|
||||||
|
for (const entry of modelEntries) {
|
||||||
|
const slug = entry[model.field];
|
||||||
|
if (!slug) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const record = slugs.get(getNonAppendedSlug(slug));
|
||||||
|
if (!record) {
|
||||||
|
slugs.set(slug, { slug, count: 1 });
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
slugs.set(record.slug, { slug: record.slug, count: record.count + 1 });
|
||||||
|
}
|
||||||
|
strapi.log.info(`[slugify] sync for ${model.uid} completed`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slugs.size) {
|
||||||
|
// create all required records
|
||||||
|
const createResponse = await strapi.db.query('plugin::slugify.slug').createMany({
|
||||||
|
data: [...slugs.values()],
|
||||||
|
});
|
||||||
|
|
||||||
|
strapi.log.info(
|
||||||
|
`[slugify] ${createResponse.count} out of ${slugs.size} slugs synced successfully`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
strapi.log.info('[slugify] No syncable slugs found');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// removes any appended number from a slug/string if found
|
||||||
|
const getNonAppendedSlug = (slug) => {
|
||||||
|
const match = slug.match('[\\-]{1}[\\d]+$');
|
||||||
|
|
||||||
|
if (!match) {
|
||||||
|
return slug;
|
||||||
|
}
|
||||||
|
|
||||||
|
return slug.replace(match[0], '');
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
syncSlugCount,
|
||||||
|
};
|
9
server/content-types/index.js
Normal file
9
server/content-types/index.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const slugSchema = require('./slug/schema.json');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
slug: {
|
||||||
|
schema: slugSchema,
|
||||||
|
},
|
||||||
|
};
|
29
server/content-types/slug/schema.json
Normal file
29
server/content-types/slug/schema.json
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"kind": "collectionType",
|
||||||
|
"collectionName": "slugs",
|
||||||
|
"info": {
|
||||||
|
"singularName": "slug",
|
||||||
|
"pluralName": "slugs",
|
||||||
|
"displayName": "slug"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"draftAndPublish": false,
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
|
"pluginOptions": {
|
||||||
|
"content-manager": {
|
||||||
|
"visible": false
|
||||||
|
},
|
||||||
|
"content-type-builder": {
|
||||||
|
"visible": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"attributes": {
|
||||||
|
"slug": {
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
"count": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
const bootstrap = require('./bootstrap');
|
const bootstrap = require('./bootstrap');
|
||||||
const config = require('./config');
|
const config = require('./config');
|
||||||
|
const contentTypes = require('./content-types');
|
||||||
const controllers = require('./controllers');
|
const controllers = require('./controllers');
|
||||||
const register = require('./register');
|
const register = require('./register');
|
||||||
const routes = require('./routes');
|
const routes = require('./routes');
|
||||||
@ -10,6 +11,7 @@ const services = require('./services');
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
bootstrap,
|
bootstrap,
|
||||||
config,
|
config,
|
||||||
|
contentTypes,
|
||||||
controllers,
|
controllers,
|
||||||
register,
|
register,
|
||||||
routes,
|
routes,
|
||||||
|
40
server/services/slug-service/buildSlug.js
Normal file
40
server/services/slug-service/buildSlug.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
const slugify = require('@sindresorhus/slugify');
|
||||||
|
|
||||||
|
const buildSlug = async (string, settings) => {
|
||||||
|
let slug = slugify(string, settings.slugifyOptions);
|
||||||
|
|
||||||
|
// slugify with count
|
||||||
|
if (!settings.slugifyWithCount) {
|
||||||
|
return slug;
|
||||||
|
}
|
||||||
|
|
||||||
|
const slugEntry = await strapi.db.query('plugin::slugify.slug').findOne({
|
||||||
|
select: ['id', 'count'],
|
||||||
|
where: { slug },
|
||||||
|
});
|
||||||
|
|
||||||
|
// if no result then count is 1 and base slug is returned
|
||||||
|
if (!slugEntry) {
|
||||||
|
await strapi.entityService.create('plugin::slugify.slug', {
|
||||||
|
data: {
|
||||||
|
slug,
|
||||||
|
count: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return slug;
|
||||||
|
}
|
||||||
|
|
||||||
|
const count = slugEntry.count + 1;
|
||||||
|
await strapi.entityService.update('plugin::slugify.slug', slugEntry.id, {
|
||||||
|
data: {
|
||||||
|
count,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return `${slug}-${count}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
buildSlug,
|
||||||
|
};
|
@ -1,10 +1,10 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const { toSlug } = require('../../utils/slugification');
|
|
||||||
const { getPluginService } = require('../../utils/getPluginService');
|
const { getPluginService } = require('../../utils/getPluginService');
|
||||||
const { shouldUpdateSlug } = require('./shoudUpdateSlug');
|
const { shouldUpdateSlug } = require('./shoudUpdateSlug');
|
||||||
const { getReferenceFieldValues } = require('./getReferenceFieldValues');
|
const { getReferenceFieldValues } = require('./getReferenceFieldValues');
|
||||||
|
const { buildSlug } = require('./buildSlug');
|
||||||
|
|
||||||
module.exports = ({ strapi }) => ({
|
module.exports = ({ strapi }) => ({
|
||||||
async slugify(ctx) {
|
async slugify(ctx) {
|
||||||
@ -40,13 +40,10 @@ module.exports = ({ strapi }) => ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
referenceFieldValues = referenceFieldValues.join(' ');
|
referenceFieldValues = referenceFieldValues.join(' ');
|
||||||
const toSlugOptions = settings.slugifyOptions;
|
|
||||||
if (settings.slugifyWithCount) {
|
|
||||||
toSlugOptions.slugifyWithCount = settings.slugifyWithCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
// update slug field based on action type
|
// update slug field based on action type
|
||||||
const slug = toSlug(referenceFieldValues, toSlugOptions);
|
const slug = await buildSlug(referenceFieldValues, settings);
|
||||||
|
|
||||||
if (ctx.action === 'beforeCreate' || ctx.action === 'beforeUpdate') {
|
if (ctx.action === 'beforeCreate' || ctx.action === 'beforeUpdate') {
|
||||||
data[field] = slug;
|
data[field] = slug;
|
||||||
} else if (ctx.action === 'afterCreate') {
|
} else if (ctx.action === 'afterCreate') {
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const _ = require('lodash');
|
|
||||||
const slugify = require('@sindresorhus/slugify');
|
|
||||||
const slugifyWithCount = slugify.counter();
|
|
||||||
|
|
||||||
const toSlug = (string, options) => {
|
|
||||||
if (options.slugifyWithCount) {
|
|
||||||
_.omit(options, 'slugifyWithCount');
|
|
||||||
return slugifyWithCount(string, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
return slugify(string, options);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
toSlug,
|
|
||||||
};
|
|
Loading…
x
Reference in New Issue
Block a user