@jhb.software/payload-alt-text-plugin 0.2.1 → 0.2.2

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/plugin.js CHANGED
@@ -53,8 +53,11 @@ export const payloadAltTextPlugin = (incomingPluginConfig)=>(incomingConfig)=>{
53
53
  admin: {
54
54
  ...collectionConfig.admin,
55
55
  listSearchableFields: [
56
- // enhance the search by adding the keywords and alt fields (if not already included)
56
+ // enhance the search by adding the filename, keywords and alt fields (if not already included)
57
57
  ...collectionConfig.admin?.listSearchableFields ?? [],
58
+ ...collectionConfig.admin?.listSearchableFields?.includes('filename') ? [] : [
59
+ 'filename'
60
+ ],
58
61
  ...collectionConfig.admin?.listSearchableFields?.includes('keywords') ? [] : [
59
62
  'keywords'
60
63
  ],
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/plugin.ts"],"sourcesContent":["import type { Config } from 'payload'\n\nimport type {\n AltTextPluginConfig,\n IncomingAltTextPluginConfig,\n} from './types/AltTextPluginConfig.js'\nimport { altTextField } from './fields/altTextField.js'\nimport { keywordsField } from './fields/keywordsField.js'\nimport { generateAltTextEndpoint } from './endpoints/generateAltText.js'\nimport { bulkGenerateAltTextsEndpoint } from './endpoints/bulkGenerateAltTexts.js'\nimport { translations } from './translations/index.js'\nimport { deepMergeSimple } from './utils/deepMergeSimple.js'\n\nexport const payloadAltTextPlugin =\n (incomingPluginConfig: IncomingAltTextPluginConfig) =>\n (incomingConfig: Config): Config => {\n const config = { ...incomingConfig }\n\n // If the plugin is disabled, return the config without modifying it\n if (incomingPluginConfig.enabled === false) {\n return config\n }\n\n const locales = config.localization\n ? config.localization.locales.map((localeConfig) =>\n typeof localeConfig === 'string' ? localeConfig : localeConfig.code,\n )\n : []\n\n const pluginConfig: AltTextPluginConfig = {\n enabled: incomingPluginConfig.enabled ?? true,\n openAIApiKey: incomingPluginConfig.openAIApiKey,\n collections: incomingPluginConfig.collections,\n maxBulkGenerateConcurrency: incomingPluginConfig.maxBulkGenerateConcurrency ?? 16,\n model: incomingPluginConfig.model ?? 'gpt-4.1-nano',\n locales: locales,\n locale: incomingPluginConfig.locale,\n getImageThumbnail: incomingPluginConfig.getImageThumbnail,\n fieldsOverride: incomingPluginConfig.fieldsOverride,\n }\n\n // Validate locale requirement for non-localized mode\n if (locales.length === 0 && !incomingPluginConfig.locale) {\n throw new Error(\n 'The alt-text plugin requires a \"locale\" option when Payload localization is disabled. ' +\n 'Please add { locale: \"en\" } (or your preferred locale) to your plugin configuration.',\n )\n }\n\n const defaultFields = [\n altTextField({\n localized: Boolean(config.localization),\n }),\n keywordsField({\n localized: Boolean(config.localization),\n }),\n ]\n\n const fields =\n incomingPluginConfig.fieldsOverride &&\n typeof incomingPluginConfig.fieldsOverride === 'function'\n ? incomingPluginConfig.fieldsOverride({ defaultFields })\n : defaultFields\n\n // Ensure collections array exists\n config.collections = config.collections || []\n\n // Map over collections and inject AI alt text fields into specified ones\n config.collections = config.collections.map((collectionConfig) => {\n if (pluginConfig.collections.includes(collectionConfig.slug)) {\n if (!collectionConfig.upload) {\n console.warn(\n `AI Alt Text Plugin: Collection \"${collectionConfig.slug}\" is not an upload collection. Skipping field injection.`,\n )\n return collectionConfig\n }\n\n return {\n ...collectionConfig,\n admin: {\n ...collectionConfig.admin,\n listSearchableFields: [\n // enhance the search by adding the keywords and alt fields (if not already included)\n ...(collectionConfig.admin?.listSearchableFields ?? []),\n ...(collectionConfig.admin?.listSearchableFields?.includes('keywords')\n ? []\n : ['keywords']),\n ...(collectionConfig.admin?.listSearchableFields?.includes('alt') ? [] : ['alt']),\n ],\n components: {\n ...(collectionConfig.admin?.components ?? {}),\n // TODO: use the beforeBulkAction custom component slot once available: https://github.com/payloadcms/payload/pull/11719\n beforeListTable: [\n ...(collectionConfig.admin?.components?.beforeListTable ?? []),\n {\n path: '@jhb.software/payload-alt-text-plugin/client#BulkGenerateAltTextsButton',\n props: {\n collectionSlug: collectionConfig.slug,\n },\n },\n ],\n },\n },\n fields: [...(collectionConfig.fields ?? []), ...fields],\n }\n }\n\n return collectionConfig\n })\n\n return {\n ...config,\n i18n: {\n ...config.i18n,\n translations: deepMergeSimple(translations, incomingConfig.i18n?.translations ?? {}),\n },\n custom: {\n ...config.custom,\n // Make plugin config available in hooks/actions\n altTextPluginConfig: pluginConfig,\n },\n endpoints: [\n ...(config.endpoints ?? []),\n {\n path: '/alt-text-plugin/generate-alt-text',\n method: 'post',\n handler: generateAltTextEndpoint,\n },\n {\n path: '/alt-text-plugin/bulk-generate-alt-texts',\n method: 'post',\n handler: bulkGenerateAltTextsEndpoint,\n },\n ],\n }\n }\n"],"names":["altTextField","keywordsField","generateAltTextEndpoint","bulkGenerateAltTextsEndpoint","translations","deepMergeSimple","payloadAltTextPlugin","incomingPluginConfig","incomingConfig","config","enabled","locales","localization","map","localeConfig","code","pluginConfig","openAIApiKey","collections","maxBulkGenerateConcurrency","model","locale","getImageThumbnail","fieldsOverride","length","Error","defaultFields","localized","Boolean","fields","collectionConfig","includes","slug","upload","console","warn","admin","listSearchableFields","components","beforeListTable","path","props","collectionSlug","i18n","custom","altTextPluginConfig","endpoints","method","handler"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/plugin.ts"],"sourcesContent":["import type { Config } from 'payload'\n\nimport type {\n AltTextPluginConfig,\n IncomingAltTextPluginConfig,\n} from './types/AltTextPluginConfig.js'\nimport { altTextField } from './fields/altTextField.js'\nimport { keywordsField } from './fields/keywordsField.js'\nimport { generateAltTextEndpoint } from './endpoints/generateAltText.js'\nimport { bulkGenerateAltTextsEndpoint } from './endpoints/bulkGenerateAltTexts.js'\nimport { translations } from './translations/index.js'\nimport { deepMergeSimple } from './utils/deepMergeSimple.js'\n\nexport const payloadAltTextPlugin =\n (incomingPluginConfig: IncomingAltTextPluginConfig) =>\n (incomingConfig: Config): Config => {\n const config = { ...incomingConfig }\n\n // If the plugin is disabled, return the config without modifying it\n if (incomingPluginConfig.enabled === false) {\n return config\n }\n\n const locales = config.localization\n ? config.localization.locales.map((localeConfig) =>\n typeof localeConfig === 'string' ? localeConfig : localeConfig.code,\n )\n : []\n\n const pluginConfig: AltTextPluginConfig = {\n enabled: incomingPluginConfig.enabled ?? true,\n openAIApiKey: incomingPluginConfig.openAIApiKey,\n collections: incomingPluginConfig.collections,\n maxBulkGenerateConcurrency: incomingPluginConfig.maxBulkGenerateConcurrency ?? 16,\n model: incomingPluginConfig.model ?? 'gpt-4.1-nano',\n locales: locales,\n locale: incomingPluginConfig.locale,\n getImageThumbnail: incomingPluginConfig.getImageThumbnail,\n fieldsOverride: incomingPluginConfig.fieldsOverride,\n }\n\n // Validate locale requirement for non-localized mode\n if (locales.length === 0 && !incomingPluginConfig.locale) {\n throw new Error(\n 'The alt-text plugin requires a \"locale\" option when Payload localization is disabled. ' +\n 'Please add { locale: \"en\" } (or your preferred locale) to your plugin configuration.',\n )\n }\n\n const defaultFields = [\n altTextField({\n localized: Boolean(config.localization),\n }),\n keywordsField({\n localized: Boolean(config.localization),\n }),\n ]\n\n const fields =\n incomingPluginConfig.fieldsOverride &&\n typeof incomingPluginConfig.fieldsOverride === 'function'\n ? incomingPluginConfig.fieldsOverride({ defaultFields })\n : defaultFields\n\n // Ensure collections array exists\n config.collections = config.collections || []\n\n // Map over collections and inject AI alt text fields into specified ones\n config.collections = config.collections.map((collectionConfig) => {\n if (pluginConfig.collections.includes(collectionConfig.slug)) {\n if (!collectionConfig.upload) {\n console.warn(\n `AI Alt Text Plugin: Collection \"${collectionConfig.slug}\" is not an upload collection. Skipping field injection.`,\n )\n return collectionConfig\n }\n\n return {\n ...collectionConfig,\n admin: {\n ...collectionConfig.admin,\n listSearchableFields: [\n // enhance the search by adding the filename, keywords and alt fields (if not already included)\n ...(collectionConfig.admin?.listSearchableFields ?? []),\n ...(collectionConfig.admin?.listSearchableFields?.includes('filename')\n ? []\n : ['filename']),\n ...(collectionConfig.admin?.listSearchableFields?.includes('keywords')\n ? []\n : ['keywords']),\n ...(collectionConfig.admin?.listSearchableFields?.includes('alt') ? [] : ['alt']),\n ],\n components: {\n ...(collectionConfig.admin?.components ?? {}),\n // TODO: use the beforeBulkAction custom component slot once available: https://github.com/payloadcms/payload/pull/11719\n beforeListTable: [\n ...(collectionConfig.admin?.components?.beforeListTable ?? []),\n {\n path: '@jhb.software/payload-alt-text-plugin/client#BulkGenerateAltTextsButton',\n props: {\n collectionSlug: collectionConfig.slug,\n },\n },\n ],\n },\n },\n fields: [...(collectionConfig.fields ?? []), ...fields],\n }\n }\n\n return collectionConfig\n })\n\n return {\n ...config,\n i18n: {\n ...config.i18n,\n translations: deepMergeSimple(translations, incomingConfig.i18n?.translations ?? {}),\n },\n custom: {\n ...config.custom,\n // Make plugin config available in hooks/actions\n altTextPluginConfig: pluginConfig,\n },\n endpoints: [\n ...(config.endpoints ?? []),\n {\n path: '/alt-text-plugin/generate-alt-text',\n method: 'post',\n handler: generateAltTextEndpoint,\n },\n {\n path: '/alt-text-plugin/bulk-generate-alt-texts',\n method: 'post',\n handler: bulkGenerateAltTextsEndpoint,\n },\n ],\n }\n }\n"],"names":["altTextField","keywordsField","generateAltTextEndpoint","bulkGenerateAltTextsEndpoint","translations","deepMergeSimple","payloadAltTextPlugin","incomingPluginConfig","incomingConfig","config","enabled","locales","localization","map","localeConfig","code","pluginConfig","openAIApiKey","collections","maxBulkGenerateConcurrency","model","locale","getImageThumbnail","fieldsOverride","length","Error","defaultFields","localized","Boolean","fields","collectionConfig","includes","slug","upload","console","warn","admin","listSearchableFields","components","beforeListTable","path","props","collectionSlug","i18n","custom","altTextPluginConfig","endpoints","method","handler"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jhb.software/payload-alt-text-plugin",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "A minimal Payload CMS plugin to generate image alt texts using OpenAI's Vision API.",
5
5
  "bugs": "https://github.com/jhb-software/payload-plugins/issues",
6
6
  "repository": "https://github.com/jhb-software/payload-plugins",
@@ -17,25 +17,25 @@
17
17
  "main": "./dist/index.js",
18
18
  "types": "./dist/index.d.ts",
19
19
  "dependencies": {
20
- "openai": "^6.6.0",
20
+ "openai": "^6.8.1",
21
21
  "p-map": "^7.0.3",
22
22
  "zod": "^4.1.12"
23
23
  },
24
24
  "peerDependencies": {
25
- "@payloadcms/ui": "^3.60.0",
25
+ "@payloadcms/ui": "^3.62.1",
26
26
  "next": "15.5.6",
27
- "payload": "^3.60.0",
27
+ "payload": "^3.62.1",
28
28
  "react": "19.2.0",
29
29
  "react-dom": "19.2.0"
30
30
  },
31
31
  "devDependencies": {
32
- "@swc/cli": "^0.7.8",
33
- "@swc/core": "^1.13.3",
32
+ "@swc/cli": "^0.7.9",
33
+ "@swc/core": "^1.15.0",
34
34
  "@types/react": "19.2.2",
35
35
  "@types/react-dom": "19.2.2",
36
36
  "copyfiles": "2.4.1",
37
37
  "prettier": "^3.6.2",
38
- "rimraf": "6.0.1",
38
+ "rimraf": "6.1.0",
39
39
  "typescript": "5.9.3"
40
40
  },
41
41
  "files": [