@websolutespa/payload-plugin-seo 2.0.1-next.2 → 2.0.1-next.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @websolutespa/payload-plugin-seo
2
2
 
3
+ ## 2.0.1-next.3
4
+
5
+ ### Patch Changes
6
+
7
+ - - Fix token list retrieval, richText replacement (payload3)
8
+
3
9
  ## 2.0.1-next.2
4
10
 
5
11
  ### Patch Changes
@@ -1,8 +1,8 @@
1
1
  import { ResponseError, ResponseSuccess } from '@websolutespa/payload-utils/server';
2
- import payload from 'payload';
3
2
  import { options } from '../options';
4
3
  import { eachTokenizableField } from '../utils/fields';
5
- const getTokens = (collections)=>{
4
+ const getTokens = (req, collections)=>{
5
+ const { payload } = req;
6
6
  const collectionConfigs = collections.length ? payload.config.collections.filter((config)=>collections.includes(config.slug)) : payload.config.collections.filter((config)=>options.collections.includes(config.slug));
7
7
  // retrieve common tokens between collections
8
8
  let tokens = collectionConfigs.reduce((acc, config)=>{
@@ -30,7 +30,7 @@ export const tokensGet = ()=>({
30
30
  try {
31
31
  const qsCollections = req.query.collections || '';
32
32
  const collections = qsCollections !== '' ? qsCollections.split(',') : [];
33
- const tokens = getTokens(collections);
33
+ const tokens = getTokens(req, collections);
34
34
  return ResponseSuccess(tokens);
35
35
  } catch (error) {
36
36
  return ResponseError(error);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/api/tokens.service.ts"],"sourcesContent":["import { ResponseError, ResponseSuccess } from '@websolutespa/payload-utils/server';\r\nimport payload, { Endpoint, PayloadRequest } from 'payload';\r\nimport { options } from '../options';\r\nimport { eachTokenizableField } from '../utils/fields';\r\n\r\nconst getTokens = (collections: string[]) => {\r\n const collectionConfigs = collections.length ?\r\n payload.config.collections.filter((config) => collections.includes(config.slug))\r\n : payload.config.collections.filter((config) => options.collections.includes(config.slug));\r\n\r\n // retrieve common tokens between collections\r\n let tokens: string[] = collectionConfigs.reduce((acc, config) => {\r\n const fields: string[] = [];\r\n eachTokenizableField(config.fields, (field) => {\r\n fields.push(`[${field.name}]`);\r\n });\r\n return acc.length ? acc.filter((field) => fields.includes(field)) : fields;\r\n }, [] as string[]);\r\n // remove duplicates\r\n tokens = [...new Set(tokens)];\r\n\r\n // merge collections tokens with custom tokens\r\n tokens = [...tokens, ...options.customTokens.map(token => `[${token.name}]`)];\r\n\r\n return tokens;\r\n};\r\n\r\nexport const tokensGet: (() => Endpoint) = () => ({\r\n path: '/seo/tokens',\r\n method: 'get',\r\n handler: async (req: PayloadRequest) => {\r\n try {\r\n const qsCollections = (req.query.collections || '') as string;\r\n const collections = qsCollections !== '' ? qsCollections.split(',') : [];\r\n const tokens = getTokens(collections);\r\n return ResponseSuccess(tokens);\r\n } catch (error) {\r\n return ResponseError(error);\r\n }\r\n },\r\n});\r\n"],"names":["ResponseError","ResponseSuccess","payload","options","eachTokenizableField","getTokens","collections","collectionConfigs","length","config","filter","includes","slug","tokens","reduce","acc","fields","field","push","name","Set","customTokens","map","token","tokensGet","path","method","handler","req","qsCollections","query","split","error"],"mappings":"AAAA,SAASA,aAAa,EAAEC,eAAe,QAAQ,qCAAqC;AACpF,OAAOC,aAA2C,UAAU;AAC5D,SAASC,OAAO,QAAQ,aAAa;AACrC,SAASC,oBAAoB,QAAQ,kBAAkB;AAEvD,MAAMC,YAAY,CAACC;IACjB,MAAMC,oBAAoBD,YAAYE,MAAM,GAC1CN,QAAQO,MAAM,CAACH,WAAW,CAACI,MAAM,CAAC,CAACD,SAAWH,YAAYK,QAAQ,CAACF,OAAOG,IAAI,KAC5EV,QAAQO,MAAM,CAACH,WAAW,CAACI,MAAM,CAAC,CAACD,SAAWN,QAAQG,WAAW,CAACK,QAAQ,CAACF,OAAOG,IAAI;IAE1F,6CAA6C;IAC7C,IAAIC,SAAmBN,kBAAkBO,MAAM,CAAC,CAACC,KAAKN;QACpD,MAAMO,SAAmB,EAAE;QAC3BZ,qBAAqBK,OAAOO,MAAM,EAAE,CAACC;YACnCD,OAAOE,IAAI,CAAC,CAAC,CAAC,EAAED,MAAME,IAAI,CAAC,CAAC,CAAC;QAC/B;QACA,OAAOJ,IAAIP,MAAM,GAAGO,IAAIL,MAAM,CAAC,CAACO,QAAUD,OAAOL,QAAQ,CAACM,UAAUD;IACtE,GAAG,EAAE;IACL,oBAAoB;IACpBH,SAAS;WAAI,IAAIO,IAAIP;KAAQ;IAE7B,8CAA8C;IAC9CA,SAAS;WAAIA;WAAWV,QAAQkB,YAAY,CAACC,GAAG,CAACC,CAAAA,QAAS,CAAC,CAAC,EAAEA,MAAMJ,IAAI,CAAC,CAAC,CAAC;KAAE;IAE7E,OAAON;AACT;AAEA,OAAO,MAAMW,YAA8B,IAAO,CAAA;QAChDC,MAAM;QACNC,QAAQ;QACRC,SAAS,OAAOC;YACd,IAAI;gBACF,MAAMC,gBAAiBD,IAAIE,KAAK,CAACxB,WAAW,IAAI;gBAChD,MAAMA,cAAcuB,kBAAkB,KAAKA,cAAcE,KAAK,CAAC,OAAO,EAAE;gBACxE,MAAMlB,SAASR,UAAUC;gBACzB,OAAOL,gBAAgBY;YACzB,EAAE,OAAOmB,OAAO;gBACd,OAAOhC,cAAcgC;YACvB;QACF;IACF,CAAA,EAAG"}
1
+ {"version":3,"sources":["../../src/api/tokens.service.ts"],"sourcesContent":["import { ResponseError, ResponseSuccess } from '@websolutespa/payload-utils/server';\r\nimport { Endpoint, PayloadRequest } from 'payload';\r\nimport { options } from '../options';\r\nimport { eachTokenizableField } from '../utils/fields';\r\n\r\nconst getTokens = (req: PayloadRequest, collections: string[]) => {\r\n const { payload } = req;\r\n const collectionConfigs = collections.length ?\r\n payload.config.collections.filter((config) => collections.includes(config.slug))\r\n : payload.config.collections.filter((config) => options.collections.includes(config.slug));\r\n\r\n // retrieve common tokens between collections\r\n let tokens: string[] = collectionConfigs.reduce((acc, config) => {\r\n const fields: string[] = [];\r\n eachTokenizableField(config.fields, (field) => {\r\n fields.push(`[${field.name}]`);\r\n });\r\n return acc.length ? acc.filter((field) => fields.includes(field)) : fields;\r\n }, [] as string[]);\r\n // remove duplicates\r\n tokens = [...new Set(tokens)];\r\n\r\n // merge collections tokens with custom tokens\r\n tokens = [...tokens, ...options.customTokens.map(token => `[${token.name}]`)];\r\n\r\n return tokens;\r\n};\r\n\r\nexport const tokensGet: (() => Endpoint) = () => ({\r\n path: '/seo/tokens',\r\n method: 'get',\r\n handler: async (req: PayloadRequest) => {\r\n try {\r\n const qsCollections = (req.query.collections || '') as string;\r\n const collections = qsCollections !== '' ? qsCollections.split(',') : [];\r\n const tokens = getTokens(req, collections);\r\n return ResponseSuccess(tokens);\r\n } catch (error) {\r\n return ResponseError(error);\r\n }\r\n },\r\n});\r\n"],"names":["ResponseError","ResponseSuccess","options","eachTokenizableField","getTokens","req","collections","payload","collectionConfigs","length","config","filter","includes","slug","tokens","reduce","acc","fields","field","push","name","Set","customTokens","map","token","tokensGet","path","method","handler","qsCollections","query","split","error"],"mappings":"AAAA,SAASA,aAAa,EAAEC,eAAe,QAAQ,qCAAqC;AAEpF,SAASC,OAAO,QAAQ,aAAa;AACrC,SAASC,oBAAoB,QAAQ,kBAAkB;AAEvD,MAAMC,YAAY,CAACC,KAAqBC;IACtC,MAAM,EAAEC,OAAO,EAAE,GAAGF;IACpB,MAAMG,oBAAoBF,YAAYG,MAAM,GAC1CF,QAAQG,MAAM,CAACJ,WAAW,CAACK,MAAM,CAAC,CAACD,SAAWJ,YAAYM,QAAQ,CAACF,OAAOG,IAAI,KAC5EN,QAAQG,MAAM,CAACJ,WAAW,CAACK,MAAM,CAAC,CAACD,SAAWR,QAAQI,WAAW,CAACM,QAAQ,CAACF,OAAOG,IAAI;IAE1F,6CAA6C;IAC7C,IAAIC,SAAmBN,kBAAkBO,MAAM,CAAC,CAACC,KAAKN;QACpD,MAAMO,SAAmB,EAAE;QAC3Bd,qBAAqBO,OAAOO,MAAM,EAAE,CAACC;YACnCD,OAAOE,IAAI,CAAC,CAAC,CAAC,EAAED,MAAME,IAAI,CAAC,CAAC,CAAC;QAC/B;QACA,OAAOJ,IAAIP,MAAM,GAAGO,IAAIL,MAAM,CAAC,CAACO,QAAUD,OAAOL,QAAQ,CAACM,UAAUD;IACtE,GAAG,EAAE;IACL,oBAAoB;IACpBH,SAAS;WAAI,IAAIO,IAAIP;KAAQ;IAE7B,8CAA8C;IAC9CA,SAAS;WAAIA;WAAWZ,QAAQoB,YAAY,CAACC,GAAG,CAACC,CAAAA,QAAS,CAAC,CAAC,EAAEA,MAAMJ,IAAI,CAAC,CAAC,CAAC;KAAE;IAE7E,OAAON;AACT;AAEA,OAAO,MAAMW,YAA8B,IAAO,CAAA;QAChDC,MAAM;QACNC,QAAQ;QACRC,SAAS,OAAOvB;YACd,IAAI;gBACF,MAAMwB,gBAAiBxB,IAAIyB,KAAK,CAACxB,WAAW,IAAI;gBAChD,MAAMA,cAAcuB,kBAAkB,KAAKA,cAAcE,KAAK,CAAC,OAAO,EAAE;gBACxE,MAAMjB,SAASV,UAAUC,KAAKC;gBAC9B,OAAOL,gBAAgBa;YACzB,EAAE,OAAOkB,OAAO;gBACd,OAAOhC,cAAcgC;YACvB;QACF;IACF,CAAA,EAAG"}
@@ -1,19 +1,18 @@
1
1
  'use client';
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
- import { useField, useFormFields } from '@payloadcms/ui';
3
+ import { useConfig, useFormFields } from '@payloadcms/ui';
4
+ import { getRouteResolver } from '@websolutespa/payload-utils';
4
5
  import * as React from 'react';
5
6
  export const Tokens = (props)=>{
6
- const { path, field } = props;
7
- const { label, required } = field;
7
+ const { config } = useConfig();
8
8
  const collectionsField = useFormFields(([fields])=>fields['collections']);
9
- const { value = [], setValue } = useField({
10
- path
11
- });
9
+ const [tokens, setTokens] = React.useState([]);
12
10
  React.useEffect(()=>{
13
11
  const fetchOptions = async ()=>{
14
12
  try {
15
13
  const collections = collectionsField?.value;
16
- const url = `${process.env.PAYLOAD_PUBLIC_BASE_PATH || ''}/api/seo/tokens?collections=${collections?.join(',') || ''}`;
14
+ const routeResolver = getRouteResolver(config);
15
+ const url = routeResolver.api(`/seo/tokens?collections=${collections?.join(',') || ''}`);
17
16
  const response = await fetch(url, {
18
17
  method: 'GET',
19
18
  credentials: 'include',
@@ -22,11 +21,10 @@ export const Tokens = (props)=>{
22
21
  }
23
22
  });
24
23
  if (response.ok) {
25
- const tokens = await response.json();
26
- console.log(tokens);
27
- setValue(tokens);
24
+ const fetchedTokens = await response.json();
25
+ setTokens(fetchedTokens);
28
26
  } else {
29
- setValue([]);
27
+ setTokens([]);
30
28
  }
31
29
  } catch (error) {
32
30
  console.error('Error fetching data:', error);
@@ -34,12 +32,13 @@ export const Tokens = (props)=>{
34
32
  };
35
33
  fetchOptions();
36
34
  }, [
37
- collectionsField
35
+ collectionsField?.value,
36
+ config
38
37
  ]);
39
38
  return /*#__PURE__*/ _jsx("div", {
40
39
  className: "tokens-list",
41
40
  children: /*#__PURE__*/ _jsx("ul", {
42
- children: value.map((token)=>/*#__PURE__*/ _jsx("li", {
41
+ children: tokens.map((token)=>/*#__PURE__*/ _jsx("li", {
43
42
  children: token
44
43
  }, token))
45
44
  })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/Tokens.tsx"],"sourcesContent":["'use client';\r\n\r\nimport { useField, useFormFields } from '@payloadcms/ui';\r\nimport { TextFieldClientProps } from 'payload';\r\nimport * as React from 'react';\r\n\r\nexport const Tokens: React.FC<TextFieldClientProps> = (props) => {\r\n const { path, field } = props;\r\n const { label, required } = field;\r\n const collectionsField = useFormFields(([fields]) => fields['collections']);\r\n const { value = [], setValue } = useField<string[]>({ path });\r\n\r\n React.useEffect(() => {\r\n const fetchOptions = async () => {\r\n try {\r\n const collections = collectionsField?.value as string[] | undefined;\r\n const url = `${(process.env.PAYLOAD_PUBLIC_BASE_PATH || '')}/api/seo/tokens?collections=${(collections?.join(',') || '')}`;\r\n const response = await fetch(url, {\r\n method: 'GET',\r\n credentials: 'include',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n });\r\n if (response.ok) {\r\n const tokens = (await response.json()) as string[];\r\n console.log(tokens);\r\n setValue(tokens);\r\n } else {\r\n setValue([]);\r\n }\r\n } catch (error) {\r\n console.error('Error fetching data:', error);\r\n }\r\n };\r\n\r\n fetchOptions();\r\n }, [collectionsField]);\r\n\r\n return (\r\n <div className=\"tokens-list\">\r\n <ul>\r\n {value.map((token) => (\r\n <li key={token}>{token}</li>\r\n ))}\r\n </ul>\r\n </div>\r\n );\r\n};\r\n"],"names":["useField","useFormFields","React","Tokens","props","path","field","label","required","collectionsField","fields","value","setValue","useEffect","fetchOptions","collections","url","process","env","PAYLOAD_PUBLIC_BASE_PATH","join","response","fetch","method","credentials","headers","ok","tokens","json","console","log","error","div","className","ul","map","token","li"],"mappings":"AAAA;;AAEA,SAASA,QAAQ,EAAEC,aAAa,QAAQ,iBAAiB;AAEzD,YAAYC,WAAW,QAAQ;AAE/B,OAAO,MAAMC,SAAyC,CAACC;IACrD,MAAM,EAAEC,IAAI,EAAEC,KAAK,EAAE,GAAGF;IACxB,MAAM,EAAEG,KAAK,EAAEC,QAAQ,EAAE,GAAGF;IAC5B,MAAMG,mBAAmBR,cAAc,CAAC,CAACS,OAAO,GAAKA,MAAM,CAAC,cAAc;IAC1E,MAAM,EAAEC,QAAQ,EAAE,EAAEC,QAAQ,EAAE,GAAGZ,SAAmB;QAAEK;IAAK;IAE3DH,MAAMW,SAAS,CAAC;QACd,MAAMC,eAAe;YACnB,IAAI;gBACF,MAAMC,cAAcN,kBAAkBE;gBACtC,MAAMK,MAAM,CAAC,EAAGC,QAAQC,GAAG,CAACC,wBAAwB,IAAI,GAAI,4BAA4B,EAAGJ,aAAaK,KAAK,QAAQ,GAAI,CAAC;gBAC1H,MAAMC,WAAW,MAAMC,MAAMN,KAAK;oBAChCO,QAAQ;oBACRC,aAAa;oBACbC,SAAS;wBACP,gBAAgB;oBAClB;gBACF;gBACA,IAAIJ,SAASK,EAAE,EAAE;oBACf,MAAMC,SAAU,MAAMN,SAASO,IAAI;oBACnCC,QAAQC,GAAG,CAACH;oBACZf,SAASe;gBACX,OAAO;oBACLf,SAAS,EAAE;gBACb;YACF,EAAE,OAAOmB,OAAO;gBACdF,QAAQE,KAAK,CAAC,wBAAwBA;YACxC;QACF;QAEAjB;IACF,GAAG;QAACL;KAAiB;IAErB,qBACE,KAACuB;QAAIC,WAAU;kBACb,cAAA,KAACC;sBACEvB,MAAMwB,GAAG,CAAC,CAACC,sBACV,KAACC;8BAAgBD;mBAARA;;;AAKnB,EAAE"}
1
+ {"version":3,"sources":["../../src/components/Tokens.tsx"],"sourcesContent":["'use client';\r\n\r\nimport { useConfig, useFormFields } from '@payloadcms/ui';\r\nimport { getRouteResolver } from '@websolutespa/payload-utils';\r\nimport { TextFieldClientProps } from 'payload';\r\nimport * as React from 'react';\r\n\r\nexport const Tokens: React.FC<TextFieldClientProps> = (props) => {\r\n const { config } = useConfig();\r\n const collectionsField = useFormFields(([fields]) => fields['collections']);\r\n const [tokens, setTokens] = React.useState<string[]>([]);\r\n\r\n React.useEffect(() => {\r\n const fetchOptions = async () => {\r\n try {\r\n const collections = collectionsField?.value as string[] | undefined;\r\n const routeResolver = getRouteResolver(config);\r\n const url = routeResolver.api(`/seo/tokens?collections=${(collections?.join(',') || '')}`);\r\n const response = await fetch(url, {\r\n method: 'GET',\r\n credentials: 'include',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n });\r\n if (response.ok) {\r\n const fetchedTokens = (await response.json()) as string[];\r\n setTokens(fetchedTokens);\r\n } else {\r\n setTokens([]);\r\n }\r\n } catch (error) {\r\n console.error('Error fetching data:', error);\r\n }\r\n };\r\n\r\n fetchOptions();\r\n }, [collectionsField?.value, config]);\r\n\r\n return (\r\n <div className=\"tokens-list\">\r\n <ul>\r\n {tokens.map((token) => (\r\n <li key={token}>{token}</li>\r\n ))}\r\n </ul>\r\n </div>\r\n );\r\n};\r\n"],"names":["useConfig","useFormFields","getRouteResolver","React","Tokens","props","config","collectionsField","fields","tokens","setTokens","useState","useEffect","fetchOptions","collections","value","routeResolver","url","api","join","response","fetch","method","credentials","headers","ok","fetchedTokens","json","error","console","div","className","ul","map","token","li"],"mappings":"AAAA;;AAEA,SAASA,SAAS,EAAEC,aAAa,QAAQ,iBAAiB;AAC1D,SAASC,gBAAgB,QAAQ,8BAA8B;AAE/D,YAAYC,WAAW,QAAQ;AAE/B,OAAO,MAAMC,SAAyC,CAACC;IACrD,MAAM,EAAEC,MAAM,EAAE,GAAGN;IACnB,MAAMO,mBAAmBN,cAAc,CAAC,CAACO,OAAO,GAAKA,MAAM,CAAC,cAAc;IAC1E,MAAM,CAACC,QAAQC,UAAU,GAAGP,MAAMQ,QAAQ,CAAW,EAAE;IAEvDR,MAAMS,SAAS,CAAC;QACd,MAAMC,eAAe;YACnB,IAAI;gBACF,MAAMC,cAAcP,kBAAkBQ;gBACtC,MAAMC,gBAAgBd,iBAAiBI;gBACvC,MAAMW,MAAMD,cAAcE,GAAG,CAAC,CAAC,wBAAwB,EAAGJ,aAAaK,KAAK,QAAQ,GAAI,CAAC;gBACzF,MAAMC,WAAW,MAAMC,MAAMJ,KAAK;oBAChCK,QAAQ;oBACRC,aAAa;oBACbC,SAAS;wBACP,gBAAgB;oBAClB;gBACF;gBACA,IAAIJ,SAASK,EAAE,EAAE;oBACf,MAAMC,gBAAiB,MAAMN,SAASO,IAAI;oBAC1CjB,UAAUgB;gBACZ,OAAO;oBACLhB,UAAU,EAAE;gBACd;YACF,EAAE,OAAOkB,OAAO;gBACdC,QAAQD,KAAK,CAAC,wBAAwBA;YACxC;QACF;QAEAf;IACF,GAAG;QAACN,kBAAkBQ;QAAOT;KAAO;IAEpC,qBACE,KAACwB;QAAIC,WAAU;kBACb,cAAA,KAACC;sBACEvB,OAAOwB,GAAG,CAAC,CAACC,sBACX,KAACC;8BAAgBD;mBAARA;;;AAKnB,EAAE"}
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","names":[],"sources":["../../src/components/TextWithTokens.tsx","../../src/components/Tokens.tsx"],"sourcesContent":[],"mappings":";;;;cASa,gBAAgB,KAAA,CAAM,GAAG;;;;cCHzB,QAAQ,KAAA,CAAM,GAAG"}
1
+ {"version":3,"file":"client.d.ts","names":[],"sources":["../../src/components/TextWithTokens.tsx","../../src/components/Tokens.tsx"],"sourcesContent":[],"mappings":";;;;cASa,gBAAgB,KAAA,CAAM,GAAG;;;;cCFzB,QAAQ,KAAA,CAAM,GAAG"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/utils/fields.ts","../src/utils/findVal.ts","../src/seo.ts"],"sourcesContent":[],"mappings":";;;;KAGY,cAAA;;EAAA,gBAAA,CAAc,EAEL,SAFK,EAAA;EAAA,YAAA,CAAA,EAGT,QAHS,EAAA;EAAA,eAEL,CAAA,EAAA,MAAA;EAAS,mBACb,CAAA,EAEO,kBAFP;EAAQ,OAED,CAAA,EAAA,OAAA;AAAkB,CAAA;AAI9B,KAAA,OAAA,GAAU,MAAH,CAAA,MAAA,EAAkB,cAAlB,CAAA,GAAA;EAAA,YAAA,EACH,cADG;CAAA;AAAG,KAIV,QAAA,GAJU;EAAM,GACZ,EAAA,MAAA;EAAc,CAAA,GAAA,EAAA,MAAA,CAAA,EAAA,MAAA;AAG9B,CAAA;AAKY,KAAA,QAAA,GAAQ;EAAA,IAAA,EAAA,MAAA;EAAA,mBAGX,EAAA,CAAA,GAAA,EAAA,cAAA,EAAA,UAAA,EACO,gBADP,EAAA,GAAA,EAAA;IACO,CAAA,GAAA,EAAA,MAAA,CAAA,EAAA,GAAA;EAAgB,CAAA,EAEpB,MAAA,EAAA,MAAA,GAAA,IAAA,EAAA,GACL,OADK,CAAA,MAAA,CAAA,GAAA,MAAA;CAAM;AACJ,KAGF,kBAAA,GAHE;EAGF,MAAA,CAAA,EACD,MADC;EAAkB,IAAA,CAAA,EAErB,MAFqB;EAAA,YACnB,CAAA,EAEM,MAFN;EAAM,MACR,CAAA,EAEE,MAFF;EAAM,MACE,CAAA,EAEN,MAFM;EAAM,KACZ,CAAA,EAAA,CAAA,IAAA,CAAA,EAAA,GAAA,EAAA,GAAA,OAAA,GAEyB,OAFzB,CAAA,OAAA,CAAA;EAAM,MACN,CAAA,EAEA,MAFA;CAAM;AAEN,KAGC,UAAA,GAHD;EAAM,WAAA,EAAA,MAAA,EAAA;EAGL,YAAA,EAEI,QAFM,EAAA;EAAA,gBAAA,EAGF,SAHE,EAAA;EAAA,eAEN,EAAA,MAAA;EAAQ,aACJ,EAAA,MAAA;EAAS,aAIpB,EAAA,MAAA;EAAQ,KACK,EADb,QACa;EAAM,OACpB,EAAA,MAAA,EAAA,GADc,MACd,EAAA;EAAO,IACC,EADR,OACQ;EAAQ,YAAA,EAAR,QAAQ;;;;;KChDZ,QAAA,GAAW,YAAY,gBAAgB,gBAAgB;iBAEnD,UAAA,QAAkB,iBAAiB;ADFvC,cCMC,kBDNa,EAAA,MAAA,EAAA;AAAA,KCQd,gBAAA,GAAmB,SDRL,GCQiB,aDRjB,GCQiC,aDRjC,GCQiD,iBDRjD;AAEL,iBCQL,kBAAA,CDRK,KAAA,ECQqB,KDRrB,CAAA,EAAA,KAAA,ICQsC,gBDRtC;AACJ,iBCWD,oBAAA,CDXC,MAAA,ECW4B,KDX5B,EAAA,EAAA,QAAA,EAAA,CAAA,KAAA,ECWuD,gBDXvD,EAAA,KAAA,EAAA,MAAA,EAAA,EAAA,MAAA,CAAA,ECWmG,KDXnG,GCW2G,KDX3G,GCWmH,GDXnH,EAAA,GAAA,OAAA,GAAA,IAAA,EAAA,QAAA,CAAA,EAAA,MAAA,CAAA,EAAA,OAAA,GAAA,IAAA;AAEO,iBCiBR,YAAA,CDjBQ,MAAA,ECiBa,KDjBb,EAAA,EAAA,IAAA,EAAA,MAAA,CAAA,ECiBqC,SDjBrC,GAAA,SAAA;AAAkB,iBC4B1B,oBAAA,CD5B0B,UAAA,EC4BO,gBD5BP,CAAA,EC4BuB,gBD5BvB,EAAA;AAI1C;;;cEZa;;;;;AFqBO,cG8OP,GH9OO,EAAA,CAAA,aAAA,EG8Oe,cH9Of,EAAA,GG8OgC,MH9OhC"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/utils/fields.ts","../src/utils/findVal.ts","../src/seo.ts"],"sourcesContent":[],"mappings":";;;;KAGY,cAAA;;EAAA,gBAAA,CAAc,EAEL,SAFK,EAAA;EAAA,YAAA,CAAA,EAGT,QAHS,EAAA;EAAA,eAEL,CAAA,EAAA,MAAA;EAAS,mBACb,CAAA,EAEO,kBAFP;EAAQ,OAED,CAAA,EAAA,OAAA;AAAkB,CAAA;AAI9B,KAAA,OAAA,GAAU,MAAH,CAAA,MAAA,EAAkB,cAAlB,CAAA,GAAA;EAAA,YAAA,EACH,cADG;CAAA;AAAG,KAIV,QAAA,GAJU;EAAM,GACZ,EAAA,MAAA;EAAc,CAAA,GAAA,EAAA,MAAA,CAAA,EAAA,MAAA;AAG9B,CAAA;AAKY,KAAA,QAAA,GAAQ;EAAA,IAAA,EAAA,MAAA;EAAA,mBAGX,EAAA,CAAA,GAAA,EAAA,cAAA,EAAA,UAAA,EACO,gBADP,EAAA,GAAA,EAAA;IACO,CAAA,GAAA,EAAA,MAAA,CAAA,EAAA,GAAA;EAAgB,CAAA,EAEpB,MAAA,EAAA,MAAA,GAAA,IAAA,EAAA,GACL,OADK,CAAA,MAAA,CAAA,GAAA,MAAA;CAAM;AACJ,KAGF,kBAAA,GAHE;EAGF,MAAA,CAAA,EACD,MADC;EAAkB,IAAA,CAAA,EAErB,MAFqB;EAAA,YACnB,CAAA,EAEM,MAFN;EAAM,MACR,CAAA,EAEE,MAFF;EAAM,MACE,CAAA,EAEN,MAFM;EAAM,KACZ,CAAA,EAAA,CAAA,IAAA,CAAA,EAAA,GAAA,EAAA,GAAA,OAAA,GAEyB,OAFzB,CAAA,OAAA,CAAA;EAAM,MACN,CAAA,EAEA,MAFA;CAAM;AAEN,KAGC,UAAA,GAHD;EAAM,WAAA,EAAA,MAAA,EAAA;EAGL,YAAA,EAEI,QAFM,EAAA;EAAA,gBAAA,EAGF,SAHE,EAAA;EAAA,eAEN,EAAA,MAAA;EAAQ,aACJ,EAAA,MAAA;EAAS,aAIpB,EAAA,MAAA;EAAQ,KACK,EADb,QACa;EAAM,OACpB,EAAA,MAAA,EAAA,GADc,MACd,EAAA;EAAO,IACC,EADR,OACQ;EAAQ,YAAA,EAAR,QAAQ;;;;;KChDZ,QAAA,GAAW,YAAY,gBAAgB,gBAAgB;iBAEnD,UAAA,QAAkB,iBAAiB;ADFvC,cCMC,kBDNa,EAAA,MAAA,EAAA;AAAA,KCQd,gBAAA,GAAmB,SDRL,GCQiB,aDRjB,GCQiC,aDRjC,GCQiD,iBDRjD;AAEL,iBCQL,kBAAA,CDRK,KAAA,ECQqB,KDRrB,CAAA,EAAA,KAAA,ICQsC,gBDRtC;AACJ,iBCWD,oBAAA,CDXC,MAAA,ECW4B,KDX5B,EAAA,EAAA,QAAA,EAAA,CAAA,KAAA,ECWuD,gBDXvD,EAAA,KAAA,EAAA,MAAA,EAAA,EAAA,MAAA,CAAA,ECWmG,KDXnG,GCW2G,KDX3G,GCWmH,GDXnH,EAAA,GAAA,OAAA,GAAA,IAAA,EAAA,QAAA,CAAA,EAAA,MAAA,CAAA,EAAA,OAAA,GAAA,IAAA;AAEO,iBCiBR,YAAA,CDjBQ,MAAA,ECiBa,KDjBb,EAAA,EAAA,IAAA,EAAA,MAAA,CAAA,ECiBqC,SDjBrC,GAAA,SAAA;AAAkB,iBC4B1B,oBAAA,CD5B0B,UAAA,EC4BO,gBD5BP,CAAA,EC4BuB,gBD5BvB,EAAA;AAI1C;;;cEZa;;;;;AFqBO,cGiPP,GHjPO,EAAA,CAAA,aAAA,EGiPe,cHjPf,EAAA,GGiPgC,MHjPhC"}
package/dist/seo.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { isObject } from '@websolutespa/bom-core';
2
- import { richTextToText } from '@websolutespa/payload-utils';
2
+ import { richTextToText, stripHtml } from '@websolutespa/payload-utils';
3
3
  import { tokensGet } from './api/tokens.service';
4
4
  import { MetatagsRule } from './collections/MetatagsRule';
5
5
  import { options } from './options';
@@ -43,7 +43,9 @@ const replaceTokens = async (req, collection, doc, str, locale)=>{
43
43
  }
44
44
  case 'richText':
45
45
  {
46
- str = str.replace(token, locale && fieldConfig?.localized ? richTextToText(fieldValue[locale.code]) ?? richTextToText(fieldValue[defaultLocale]) : richTextToText(fieldValue));
46
+ const val = locale && fieldConfig?.localized ? fieldValue[locale.code] ?? fieldValue[defaultLocale] ?? (typeof fieldValue === 'object' && fieldValue !== null ? Object.values(fieldValue)[0] : fieldValue) : fieldValue;
47
+ const textVal = typeof val === 'string' ? stripHtml(val) : richTextToText(val);
48
+ str = str.replace(token, textVal || '');
47
49
  break;
48
50
  }
49
51
  case 'relationship':
@@ -89,7 +91,7 @@ const replaceTokens = async (req, collection, doc, str, locale)=>{
89
91
  }
90
92
  }
91
93
  }
92
- return str;
94
+ return str.trim();
93
95
  };
94
96
  const setDocMetatags = async ({ req, doc, collection })=>{
95
97
  try {
package/dist/seo.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/seo.ts"],"sourcesContent":["import { isObject } from '@websolutespa/bom-core';\r\nimport { richTextToText } from '@websolutespa/payload-utils';\r\nimport { CollectionAfterOperationHook, CollectionConfig, Config, Field, Locale, Payload, PayloadRequest, Plugin, TypeWithID } from 'payload';\r\nimport { tokensGet } from './api/tokens.service';\r\nimport { MetatagsRule } from './collections/MetatagsRule';\r\nimport { options } from './options';\r\nimport { SeoInitOptions } from './types';\r\nimport { fromCache } from './utils/cache';\r\nimport { getTokenizableFields } from './utils/fields';\r\nimport { findVal } from './utils/findVal';\r\n\r\nexport type MetatagsRule = {\r\n id: string;\r\n title: Record<string, string>;\r\n description: Record<string, string>;\r\n keywords: Record<string, string>;\r\n [key: string]: Record<string, string> | string;\r\n};\r\n\r\nexport type DocWithMetas = TypeWithID & {\r\n [key: string]: unknown;\r\n meta?: {\r\n title?: string;\r\n description?: string;\r\n keywords?: string;\r\n [key: string]: any;\r\n };\r\n};\r\n\r\nconst replaceTokens = async (req: PayloadRequest, collection: CollectionConfig, doc: DocWithMetas, str: string, locale: Locale | null) => {\r\n const tokens: string[] = str.match(/\\[(.*?)\\]/g) || [];\r\n\r\n const defaultLocale = req.payload.config.localization ? req.payload.config.localization.defaultLocale : 'en';\r\n const fields = getTokenizableFields(collection);\r\n\r\n for (const token of tokens) {\r\n const customToken = options.customTokens.find(customToken => `[${customToken.name}]` === token);\r\n\r\n if (customToken) {\r\n // token is a custom token\r\n try {\r\n str = str.replace(token, await customToken.replacementFunction(req, collection, doc, locale));\r\n }\r\n catch (error) {\r\n console.error(`Error while replacing customtoken \"${token}\": ${error}`);\r\n }\r\n }\r\n else {\r\n // token is a doc field\r\n const fieldName = token.replace(/[[\\]]/g, '');\r\n\r\n const fieldConfig = fields.find(f => f.name === fieldName);\r\n if (!fieldConfig) {\r\n // remove token if field not found\r\n str = str.replace(token, '');\r\n continue;\r\n }\r\n\r\n const fieldValue = findVal(doc, fieldName);\r\n if (!fieldValue || Object.keys(fieldValue).length === 0) {\r\n // remove token if field is empty\r\n str = str.replace(token, '');\r\n continue;\r\n }\r\n\r\n switch (fieldConfig?.type) {\r\n case 'text':\r\n case 'textarea': {\r\n str = str.replace(token, locale && fieldConfig?.localized ?\r\n fieldValue[locale.code] ?? fieldValue[defaultLocale] ?? Object.values(fieldValue)[0] :\r\n fieldValue\r\n );\r\n break;\r\n }\r\n\r\n case 'richText': {\r\n str = str.replace(token, locale && fieldConfig?.localized ?\r\n richTextToText(fieldValue[locale.code]) ?? richTextToText(fieldValue[defaultLocale]) :\r\n richTextToText(fieldValue)\r\n );\r\n break;\r\n }\r\n\r\n case 'relationship': {\r\n const isPolymorphicRel = Array.isArray(fieldConfig.relationTo);\r\n if (!isPolymorphicRel) {\r\n if (locale && fieldConfig.hasMany) {\r\n // payload seems to return an array of ids for hasMany relationships (when requesting locale=all).\r\n // We replace the token with a comma-separated list of ids.\r\n str = str.replace(token, fieldValue.map((id: string) => id).join(', '));\r\n }\r\n else {\r\n // hasMany = false or request is specific locale\r\n const relatedConfig = req.payload.config.collections.find(c => c.slug === fieldConfig.relationTo);\r\n if (relatedConfig) {\r\n const relatedCollfields = getTokenizableFields(relatedConfig);\r\n const titleField = relatedConfig?.admin?.useAsTitle ?\r\n relatedCollfields.find(f => f.name === relatedConfig.admin.useAsTitle) : relatedCollfields.find(f => f.name === 'title');\r\n if (titleField) {\r\n if (fieldConfig.hasMany) {\r\n // hasMany = true and request is specific locale\r\n const titleFieldValue = fieldValue.map((value: any) => findVal(value, titleField.name)).join(', ');\r\n str = str.replace(token, titleFieldValue);\r\n }\r\n else {\r\n // hasMany = false and request is either specific locale or all locales\r\n const titleFieldValue = findVal(fieldValue, titleField.name);\r\n if (!titleFieldValue || Object.keys(titleFieldValue).length === 0) {\r\n str = str.replace(token, '');\r\n }\r\n else {\r\n str = str.replace(token, locale && titleField?.localized ?\r\n titleFieldValue[locale.code] ?? titleFieldValue[defaultLocale] : titleFieldValue);\r\n }\r\n }\r\n }\r\n else {\r\n // remove token if neither title nor default fallback title field found\r\n str = str.replace(token, '');\r\n }\r\n }\r\n }\r\n }\r\n else {\r\n // todo: handle polymorphic relationships\r\n str = str.replace(token, '');\r\n }\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return str;\r\n};\r\n\r\nconst setDocMetatags = async ({\r\n req,\r\n doc,\r\n collection,\r\n}: {\r\n req: PayloadRequest;\r\n doc: DocWithMetas;\r\n collection: CollectionConfig;\r\n}): Promise<DocWithMetas> => {\r\n try {\r\n const { payload } = req;\r\n const defaultLocale = req.payload.config.localization ? req.payload.config.localization.defaultLocale : 'en';\r\n\r\n // get all rules for this collection\r\n const result = await fromCache(\r\n async () => await payload.find({\r\n collection: options.slug.metatagsRule,\r\n where: {\r\n or: [\r\n { collections: { equals: '' } },\r\n { collections: { equals: [] } },\r\n { collections: { equals: null } },\r\n { collections: { exists: false } },\r\n { collections: { contains: collection.slug } },\r\n ],\r\n },\r\n pagination: false,\r\n overrideAccess: true,\r\n locale: 'all',\r\n }),\r\n 'metatags-rules-' + collection.slug,\r\n 60 // TODO: add to plugin options\r\n );\r\n let rules = result.docs as MetatagsRule[];\r\n // sort rules by \"priority\": global (empty collections) last\r\n rules = rules.sort((a, b) => (a.collections || []).length === 0 ? 1 : (b.collections || []).length === 0 ? -1 : 0);\r\n\r\n // set meta fields values\r\n const metaFields = ['title', 'description', 'keywords', ...options.additionalFields.map(field => field.name)];\r\n for (const rule of rules) {\r\n for (const metafield of metaFields) {\r\n doc.meta = doc.meta || {};\r\n\r\n if (doc.meta[metafield]) {\r\n // if doc meta field is already set, skip\r\n continue;\r\n }\r\n\r\n if (req.locale === 'all') {\r\n const locales = req.payload?.config.localization ? req.payload.config.localization.locales : [];\r\n for (const locale of locales) {\r\n // put rule value in doc meta field (for this specific locale) and replace tokens\r\n let ruleValue = rule[metafield];\r\n if (isObject(ruleValue)) {\r\n ruleValue = ruleValue[locale.code] ?? ruleValue[defaultLocale] ?? Object.values(ruleValue)[0];\r\n }\r\n if (ruleValue) {\r\n doc.meta[metafield] = doc.meta[metafield] || {};\r\n doc.meta[metafield][locale.code] = await replaceTokens(req, collection, doc, ruleValue, locale);\r\n }\r\n }\r\n }\r\n else {\r\n // put rule value in doc meta field and replace tokens\r\n let ruleValue = rule[metafield];\r\n if (isObject(ruleValue)) {\r\n ruleValue = ruleValue[req.locale ?? defaultLocale] ?? ruleValue[defaultLocale] ?? Object.values(ruleValue)[0];\r\n }\r\n if (ruleValue) {\r\n doc.meta[metafield] = await replaceTokens(req, collection, doc, ruleValue, null);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n catch (error) {\r\n console.error(`Error while setting seo metatags: ${error}`);\r\n }\r\n\r\n return doc;\r\n};\r\n\r\nconst setCollectionMetatags: CollectionAfterOperationHook = async ({\r\n args,\r\n operation,\r\n result,\r\n}) => {\r\n const { req, collection } = args;\r\n\r\n if (req?.query && req.query[options.qsMetatagsRules] === undefined) {\r\n return result;\r\n }\r\n\r\n if (operation !== 'find') {\r\n if (result && typeof result === 'object' && !Array.isArray(result) && !('docs' in result)) {\r\n const updatedDoc = await setDocMetatags({\r\n req: req as PayloadRequest,\r\n doc: result as DocWithMetas,\r\n collection: collection.config,\r\n });\r\n\r\n return updatedDoc;\r\n }\r\n } else if (operation === 'find' && req?.pathname === '/store') {\r\n if (result && typeof result === 'object' && 'docs' in result && Array.isArray(result.docs)) {\r\n const documentPromises = result.docs.map(async doc => {\r\n return await setDocMetatags({\r\n req: req as PayloadRequest,\r\n doc: doc as DocWithMetas,\r\n collection: collection.config,\r\n });\r\n });\r\n\r\n const updatedDocs = await Promise.all(documentPromises);\r\n result.docs = updatedDocs;\r\n\r\n return result;\r\n }\r\n }\r\n\r\n return result;\r\n};\r\n\r\nexport const seo = (sourceOptions: SeoInitOptions): Plugin => (sourceConfig: Config): Config => {\r\n if (sourceOptions.enabled === false) {\r\n return sourceConfig;\r\n }\r\n // set plugin options\r\n options.collections = sourceOptions.collections ? Object.assign(options.collections, sourceOptions.collections)\r\n : Object.assign(options.collections, sourceConfig.collections?.map(x => x.slug));\r\n options.additionalFields = sourceOptions.additionalFields || [];\r\n options.customTokens = sourceOptions.customTokens ? Object.assign(options.customTokens, sourceOptions.customTokens) : [];\r\n options.qsMetatagsRules = sourceOptions.qsMetatagsRules || 'seoMetatagsRules';\r\n\r\n // replace meta tokens\r\n const collections = sourceConfig.collections?.filter(collection => options.collections.includes(collection.slug));\r\n collections?.forEach(collection => {\r\n collection.hooks = {\r\n ...collection.hooks,\r\n afterOperation: [\r\n ...(collection.hooks?.afterOperation || []),\r\n setCollectionMetatags,\r\n ],\r\n };\r\n });\r\n\r\n const targetConfig: Config = {\r\n ...sourceConfig,\r\n collections: [\r\n ...(sourceConfig.collections || []),\r\n {\r\n ...MetatagsRule,\r\n fields: [\r\n ...MetatagsRule.fields,\r\n ...options.additionalFields.map(field => field.type == 'text' || field.type == 'textarea' ?\r\n {\r\n ...field,\r\n admin: {\r\n ...field.admin,\r\n components: {\r\n ...field.admin?.components,\r\n Field: '@websolutespa/payload-plugin-seo/client#TextWithTokens',\r\n },\r\n },\r\n } : field),\r\n ] as Field[],\r\n access: {\r\n ...MetatagsRule.access,\r\n ...sourceOptions.metatagsRulesAccess,\r\n },\r\n },\r\n ],\r\n endpoints: [\r\n ...sourceConfig.endpoints || [],\r\n tokensGet(),\r\n ],\r\n onInit: async (payload: Payload) => {\r\n if (typeof sourceConfig.onInit === 'function') {\r\n await sourceConfig.onInit(payload);\r\n }\r\n console.log('@websolutespa/payload-plugin-seo.onInit');\r\n },\r\n };\r\n\r\n return targetConfig;\r\n};\r\n\r\nexport default seo;\r\n"],"names":["isObject","richTextToText","tokensGet","MetatagsRule","options","fromCache","getTokenizableFields","findVal","replaceTokens","req","collection","doc","str","locale","tokens","match","defaultLocale","payload","config","localization","fields","token","customToken","customTokens","find","name","replace","replacementFunction","error","console","fieldName","fieldConfig","f","fieldValue","Object","keys","length","type","localized","code","values","isPolymorphicRel","Array","isArray","relationTo","hasMany","map","id","join","relatedConfig","collections","c","slug","relatedCollfields","titleField","admin","useAsTitle","titleFieldValue","value","setDocMetatags","result","metatagsRule","where","or","equals","exists","contains","pagination","overrideAccess","rules","docs","sort","a","b","metaFields","additionalFields","field","rule","metafield","meta","locales","ruleValue","setCollectionMetatags","args","operation","query","qsMetatagsRules","undefined","updatedDoc","pathname","documentPromises","updatedDocs","Promise","all","seo","sourceOptions","sourceConfig","enabled","assign","x","filter","includes","forEach","hooks","afterOperation","targetConfig","components","Field","access","metatagsRulesAccess","endpoints","onInit","log"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/seo.ts"],"sourcesContent":["import { isObject } from '@websolutespa/bom-core';\r\nimport { richTextToText, stripHtml } from '@websolutespa/payload-utils';\r\nimport { CollectionAfterOperationHook, CollectionConfig, Config, Field, Locale, Payload, PayloadRequest, Plugin, TypeWithID } from 'payload';\r\nimport { tokensGet } from './api/tokens.service';\r\nimport { MetatagsRule } from './collections/MetatagsRule';\r\nimport { options } from './options';\r\nimport { SeoInitOptions } from './types';\r\nimport { fromCache } from './utils/cache';\r\nimport { getTokenizableFields } from './utils/fields';\r\nimport { findVal } from './utils/findVal';\r\n\r\nexport type MetatagsRule = {\r\n id: string;\r\n title: Record<string, string>;\r\n description: Record<string, string>;\r\n keywords: Record<string, string>;\r\n [key: string]: Record<string, string> | string;\r\n};\r\n\r\nexport type DocWithMetas = TypeWithID & {\r\n [key: string]: unknown;\r\n meta?: {\r\n title?: string;\r\n description?: string;\r\n keywords?: string;\r\n [key: string]: any;\r\n };\r\n};\r\n\r\nconst replaceTokens = async (req: PayloadRequest, collection: CollectionConfig, doc: DocWithMetas, str: string, locale: Locale | null) => {\r\n const tokens: string[] = str.match(/\\[(.*?)\\]/g) || [];\r\n\r\n const defaultLocale = req.payload.config.localization ? req.payload.config.localization.defaultLocale : 'en';\r\n const fields = getTokenizableFields(collection);\r\n\r\n for (const token of tokens) {\r\n const customToken = options.customTokens.find(customToken => `[${customToken.name}]` === token);\r\n\r\n if (customToken) {\r\n // token is a custom token\r\n try {\r\n str = str.replace(token, await customToken.replacementFunction(req, collection, doc, locale));\r\n }\r\n catch (error) {\r\n console.error(`Error while replacing customtoken \"${token}\": ${error}`);\r\n }\r\n }\r\n else {\r\n // token is a doc field\r\n const fieldName = token.replace(/[[\\]]/g, '');\r\n\r\n const fieldConfig = fields.find(f => f.name === fieldName);\r\n if (!fieldConfig) {\r\n // remove token if field not found\r\n str = str.replace(token, '');\r\n continue;\r\n }\r\n\r\n const fieldValue = findVal(doc, fieldName);\r\n if (!fieldValue || Object.keys(fieldValue).length === 0) {\r\n // remove token if field is empty\r\n str = str.replace(token, '');\r\n continue;\r\n }\r\n\r\n switch (fieldConfig?.type) {\r\n case 'text':\r\n case 'textarea': {\r\n str = str.replace(token, locale && fieldConfig?.localized ?\r\n fieldValue[locale.code] ?? fieldValue[defaultLocale] ?? Object.values(fieldValue)[0] :\r\n fieldValue\r\n );\r\n break;\r\n }\r\n\r\n case 'richText': {\r\n const val = locale && fieldConfig?.localized ?\r\n (fieldValue[locale.code] ?? fieldValue[defaultLocale] ?? (typeof fieldValue === 'object' && fieldValue !== null ? Object.values(fieldValue)[0] : fieldValue)) :\r\n fieldValue;\r\n\r\n const textVal = typeof val === 'string' ? stripHtml(val) : richTextToText(val);\r\n\r\n str = str.replace(token, textVal || '');\r\n break;\r\n }\r\n\r\n case 'relationship': {\r\n const isPolymorphicRel = Array.isArray(fieldConfig.relationTo);\r\n if (!isPolymorphicRel) {\r\n if (locale && fieldConfig.hasMany) {\r\n // payload seems to return an array of ids for hasMany relationships (when requesting locale=all).\r\n // We replace the token with a comma-separated list of ids.\r\n str = str.replace(token, fieldValue.map((id: string) => id).join(', '));\r\n }\r\n else {\r\n // hasMany = false or request is specific locale\r\n const relatedConfig = req.payload.config.collections.find(c => c.slug === fieldConfig.relationTo);\r\n if (relatedConfig) {\r\n const relatedCollfields = getTokenizableFields(relatedConfig);\r\n const titleField = relatedConfig?.admin?.useAsTitle ?\r\n relatedCollfields.find(f => f.name === relatedConfig.admin.useAsTitle) : relatedCollfields.find(f => f.name === 'title');\r\n if (titleField) {\r\n if (fieldConfig.hasMany) {\r\n // hasMany = true and request is specific locale\r\n const titleFieldValue = fieldValue.map((value: any) => findVal(value, titleField.name)).join(', ');\r\n str = str.replace(token, titleFieldValue);\r\n }\r\n else {\r\n // hasMany = false and request is either specific locale or all locales\r\n const titleFieldValue = findVal(fieldValue, titleField.name);\r\n if (!titleFieldValue || Object.keys(titleFieldValue).length === 0) {\r\n str = str.replace(token, '');\r\n }\r\n else {\r\n str = str.replace(token, locale && titleField?.localized ?\r\n titleFieldValue[locale.code] ?? titleFieldValue[defaultLocale] : titleFieldValue);\r\n }\r\n }\r\n }\r\n else {\r\n // remove token if neither title nor default fallback title field found\r\n str = str.replace(token, '');\r\n }\r\n }\r\n }\r\n }\r\n else {\r\n // todo: handle polymorphic relationships\r\n str = str.replace(token, '');\r\n }\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return str.trim();\r\n};\r\n\r\nconst setDocMetatags = async ({\r\n req,\r\n doc,\r\n collection,\r\n}: {\r\n req: PayloadRequest;\r\n doc: DocWithMetas;\r\n collection: CollectionConfig;\r\n}): Promise<DocWithMetas> => {\r\n try {\r\n const { payload } = req;\r\n const defaultLocale = req.payload.config.localization ? req.payload.config.localization.defaultLocale : 'en';\r\n\r\n // get all rules for this collection\r\n const result = await fromCache(\r\n async () => await payload.find({\r\n collection: options.slug.metatagsRule,\r\n where: {\r\n or: [\r\n { collections: { equals: '' } },\r\n { collections: { equals: [] } },\r\n { collections: { equals: null } },\r\n { collections: { exists: false } },\r\n { collections: { contains: collection.slug } },\r\n ],\r\n },\r\n pagination: false,\r\n overrideAccess: true,\r\n locale: 'all',\r\n }),\r\n 'metatags-rules-' + collection.slug,\r\n 60 // TODO: add to plugin options\r\n );\r\n let rules = result.docs as MetatagsRule[];\r\n // sort rules by \"priority\": global (empty collections) last\r\n rules = rules.sort((a, b) => (a.collections || []).length === 0 ? 1 : (b.collections || []).length === 0 ? -1 : 0);\r\n\r\n // set meta fields values\r\n const metaFields = ['title', 'description', 'keywords', ...options.additionalFields.map(field => field.name)];\r\n for (const rule of rules) {\r\n for (const metafield of metaFields) {\r\n doc.meta = doc.meta || {};\r\n\r\n if (doc.meta[metafield]) {\r\n // if doc meta field is already set, skip\r\n continue;\r\n }\r\n\r\n if (req.locale === 'all') {\r\n const locales = req.payload?.config.localization ? req.payload.config.localization.locales : [];\r\n for (const locale of locales) {\r\n // put rule value in doc meta field (for this specific locale) and replace tokens\r\n let ruleValue = rule[metafield];\r\n if (isObject(ruleValue)) {\r\n ruleValue = ruleValue[locale.code] ?? ruleValue[defaultLocale] ?? Object.values(ruleValue)[0];\r\n }\r\n if (ruleValue) {\r\n doc.meta[metafield] = doc.meta[metafield] || {};\r\n doc.meta[metafield][locale.code] = await replaceTokens(req, collection, doc, ruleValue, locale);\r\n }\r\n }\r\n }\r\n else {\r\n // put rule value in doc meta field and replace tokens\r\n let ruleValue = rule[metafield];\r\n if (isObject(ruleValue)) {\r\n ruleValue = ruleValue[req.locale ?? defaultLocale] ?? ruleValue[defaultLocale] ?? Object.values(ruleValue)[0];\r\n }\r\n if (ruleValue) {\r\n doc.meta[metafield] = await replaceTokens(req, collection, doc, ruleValue, null);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n catch (error) {\r\n console.error(`Error while setting seo metatags: ${error}`);\r\n }\r\n\r\n return doc;\r\n};\r\n\r\nconst setCollectionMetatags: CollectionAfterOperationHook = async ({\r\n args,\r\n operation,\r\n result,\r\n}) => {\r\n const { req, collection } = args;\r\n\r\n if (req?.query && req.query[options.qsMetatagsRules] === undefined) {\r\n return result;\r\n }\r\n\r\n if (operation !== 'find') {\r\n if (result && typeof result === 'object' && !Array.isArray(result) && !('docs' in result)) {\r\n const updatedDoc = await setDocMetatags({\r\n req: req as PayloadRequest,\r\n doc: result as DocWithMetas,\r\n collection: collection.config,\r\n });\r\n\r\n return updatedDoc;\r\n }\r\n } else if (operation === 'find' && req?.pathname === '/store') {\r\n if (result && typeof result === 'object' && 'docs' in result && Array.isArray(result.docs)) {\r\n const documentPromises = result.docs.map(async doc => {\r\n return await setDocMetatags({\r\n req: req as PayloadRequest,\r\n doc: doc as DocWithMetas,\r\n collection: collection.config,\r\n });\r\n });\r\n\r\n const updatedDocs = await Promise.all(documentPromises);\r\n result.docs = updatedDocs;\r\n\r\n return result;\r\n }\r\n }\r\n\r\n return result;\r\n};\r\n\r\nexport const seo = (sourceOptions: SeoInitOptions): Plugin => (sourceConfig: Config): Config => {\r\n if (sourceOptions.enabled === false) {\r\n return sourceConfig;\r\n }\r\n // set plugin options\r\n options.collections = sourceOptions.collections ? Object.assign(options.collections, sourceOptions.collections)\r\n : Object.assign(options.collections, sourceConfig.collections?.map(x => x.slug));\r\n options.additionalFields = sourceOptions.additionalFields || [];\r\n options.customTokens = sourceOptions.customTokens ? Object.assign(options.customTokens, sourceOptions.customTokens) : [];\r\n options.qsMetatagsRules = sourceOptions.qsMetatagsRules || 'seoMetatagsRules';\r\n\r\n // replace meta tokens\r\n const collections = sourceConfig.collections?.filter(collection => options.collections.includes(collection.slug));\r\n collections?.forEach(collection => {\r\n collection.hooks = {\r\n ...collection.hooks,\r\n afterOperation: [\r\n ...(collection.hooks?.afterOperation || []),\r\n setCollectionMetatags,\r\n ],\r\n };\r\n });\r\n\r\n const targetConfig: Config = {\r\n ...sourceConfig,\r\n collections: [\r\n ...(sourceConfig.collections || []),\r\n {\r\n ...MetatagsRule,\r\n fields: [\r\n ...MetatagsRule.fields,\r\n ...options.additionalFields.map(field => field.type == 'text' || field.type == 'textarea' ?\r\n {\r\n ...field,\r\n admin: {\r\n ...field.admin,\r\n components: {\r\n ...field.admin?.components,\r\n Field: '@websolutespa/payload-plugin-seo/client#TextWithTokens',\r\n },\r\n },\r\n } : field),\r\n ] as Field[],\r\n access: {\r\n ...MetatagsRule.access,\r\n ...sourceOptions.metatagsRulesAccess,\r\n },\r\n },\r\n ],\r\n endpoints: [\r\n ...sourceConfig.endpoints || [],\r\n tokensGet(),\r\n ],\r\n onInit: async (payload: Payload) => {\r\n if (typeof sourceConfig.onInit === 'function') {\r\n await sourceConfig.onInit(payload);\r\n }\r\n console.log('@websolutespa/payload-plugin-seo.onInit');\r\n },\r\n };\r\n\r\n return targetConfig;\r\n};\r\n\r\nexport default seo;\r\n"],"names":["isObject","richTextToText","stripHtml","tokensGet","MetatagsRule","options","fromCache","getTokenizableFields","findVal","replaceTokens","req","collection","doc","str","locale","tokens","match","defaultLocale","payload","config","localization","fields","token","customToken","customTokens","find","name","replace","replacementFunction","error","console","fieldName","fieldConfig","f","fieldValue","Object","keys","length","type","localized","code","values","val","textVal","isPolymorphicRel","Array","isArray","relationTo","hasMany","map","id","join","relatedConfig","collections","c","slug","relatedCollfields","titleField","admin","useAsTitle","titleFieldValue","value","trim","setDocMetatags","result","metatagsRule","where","or","equals","exists","contains","pagination","overrideAccess","rules","docs","sort","a","b","metaFields","additionalFields","field","rule","metafield","meta","locales","ruleValue","setCollectionMetatags","args","operation","query","qsMetatagsRules","undefined","updatedDoc","pathname","documentPromises","updatedDocs","Promise","all","seo","sourceOptions","sourceConfig","enabled","assign","x","filter","includes","forEach","hooks","afterOperation","targetConfig","components","Field","access","metatagsRulesAccess","endpoints","onInit","log"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@websolutespa/payload-plugin-seo",
3
- "version": "2.0.1-next.2",
3
+ "version": "2.0.1-next.3",
4
4
  "description": "SEO plugin for PayloadCms",
5
5
  "keywords": [
6
6
  "payload",