From 7bae8f0c3e5a9111899618f0676092c65f4bcee5 Mon Sep 17 00:00:00 2001 From: Rui S Date: Thu, 19 Sep 2024 15:40:23 +0100 Subject: [PATCH 1/9] change to Lexical rich text editor - replaced slate editor; --- package.json | 1 + src/payload/payload.config.ts | 7 +- yarn.lock | 249 +++++++++++++++++++++++++++++++++- 3 files changed, 251 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 1912282..398ecfe 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "@payloadcms/plugin-nested-docs": "^1.0.8", "@payloadcms/plugin-redirects": "^1.0.0", "@payloadcms/plugin-seo": "^1.0.10", + "@payloadcms/richtext-lexical": "^0.11.3", "@payloadcms/richtext-slate": "^1.0.0", "cross-env": "^7.0.3", "dotenv": "^8.2.0", diff --git a/src/payload/payload.config.ts b/src/payload/payload.config.ts index 11045d6..5e0de2a 100644 --- a/src/payload/payload.config.ts +++ b/src/payload/payload.config.ts @@ -20,6 +20,7 @@ import BeforeLogin from './components/BeforeLogin' import { Footer } from './globals/Footer' import { Header } from './globals/Header' import { Settings } from './globals/Settings' +import { InlineCodeTextFeature, lexicalEditor, TreeViewFeature } from "@payloadcms/richtext-lexical"; dotenv.config({ path: path.resolve(__dirname, '../../.env'), @@ -52,7 +53,11 @@ export default buildConfig({ }, }), }, - editor: slateEditor({}), + editor: lexicalEditor({ + features: ({defaultFeatures}) => [ + ...defaultFeatures, + ] + }), db: mongooseAdapter({ url: process.env.DATABASE_URI, }), diff --git a/yarn.lock b/yarn.lock index d025270..2e130cd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1398,6 +1398,166 @@ resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60" integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA== +"@lexical/clipboard@0.13.1": + version "0.13.1" + resolved "https://registry.yarnpkg.com/@lexical/clipboard/-/clipboard-0.13.1.tgz#ca132306129974ea2c9e51d6a8637f8fcffcdb3d" + integrity sha512-gMSbVeqb7S+XAi/EMMlwl+FCurLPugN2jAXcp5k5ZaUd7be8B+iupbYdoKkjt4qBhxmvmfe9k46GoC0QOPl/nw== + dependencies: + "@lexical/html" "0.13.1" + "@lexical/list" "0.13.1" + "@lexical/selection" "0.13.1" + "@lexical/utils" "0.13.1" + +"@lexical/code@0.13.1": + version "0.13.1" + resolved "https://registry.yarnpkg.com/@lexical/code/-/code-0.13.1.tgz#e13688390582a4b63a639daff1f16bcb82aa854d" + integrity sha512-QK77r3QgEtJy96ahYXNgpve8EY64BQgBSnPDOuqVrLdl92nPzjqzlsko2OZldlrt7gjXcfl9nqfhZ/CAhStfOg== + dependencies: + "@lexical/utils" "0.13.1" + prismjs "^1.27.0" + +"@lexical/dragon@0.13.1": + version "0.13.1" + resolved "https://registry.yarnpkg.com/@lexical/dragon/-/dragon-0.13.1.tgz#32ba02bff4d8f02a6317d874671ee0b0a2dcdc53" + integrity sha512-aNlqfif4//jW7gOxbBgdrbDovU6m3EwQrUw+Y/vqRkY+sWmloyAUeNwCPH1QP3Q5cvfolzOeN5igfBljsFr+1g== + +"@lexical/hashtag@0.13.1": + version "0.13.1" + resolved "https://registry.yarnpkg.com/@lexical/hashtag/-/hashtag-0.13.1.tgz#eb273c199a0115ec0f0191c2449e97f512360f2e" + integrity sha512-Dl0dUG4ZXNjYYuAUR0GMGpLGsA+cps2/ln3xEmy28bZR0sKkjXugsu2QOIxZjYIPBewDrXzPcvK8md45cMYoSg== + dependencies: + "@lexical/utils" "0.13.1" + +"@lexical/headless@0.13.1": + version "0.13.1" + resolved "https://registry.yarnpkg.com/@lexical/headless/-/headless-0.13.1.tgz#61e475495de49a4c5732e383e1d5f75fc5e39664" + integrity sha512-W2mLUuWPrsyf2n73NWM8nKiBI11lEpVVzKE0OzMsjTskv5+AAMaeu1wQ7M1508vKdCcUZwA6AOh3To/hstLEpw== + +"@lexical/history@0.13.1": + version "0.13.1" + resolved "https://registry.yarnpkg.com/@lexical/history/-/history-0.13.1.tgz#3bb54716dc69779d3b35894bd72637a7fc2ed284" + integrity sha512-cZXt30MalEEiRaflE9tHeGYnwT1xSDjXLsf9M409DSU9POJyZ1fsULJrG1tWv2uFQOhwal33rve9+MatUlITrg== + dependencies: + "@lexical/utils" "0.13.1" + +"@lexical/html@0.13.1": + version "0.13.1" + resolved "https://registry.yarnpkg.com/@lexical/html/-/html-0.13.1.tgz#e56035d0c6528ffb932390e0d3d357c82f69253a" + integrity sha512-XkZrnCSHIUavtpMol6aG8YsJ5KqC9hMxEhAENf3HTGi3ocysCByyXOyt1EhEYpjJvgDG4wRqt25xGDbLjj1/sA== + dependencies: + "@lexical/selection" "0.13.1" + "@lexical/utils" "0.13.1" + +"@lexical/link@0.13.1": + version "0.13.1" + resolved "https://registry.yarnpkg.com/@lexical/link/-/link-0.13.1.tgz#f1c4c12c828c0251e5d7fb4fb336f2d62380fc57" + integrity sha512-7E3B2juL2UoMj2n+CiyFZ7tlpsdViAoIE7MpegXwfe/VQ66wFwk/VxGTa/69ng2EoF7E0kh+SldvGQDrWAWb1g== + dependencies: + "@lexical/utils" "0.13.1" + +"@lexical/list@0.13.1": + version "0.13.1" + resolved "https://registry.yarnpkg.com/@lexical/list/-/list-0.13.1.tgz#461cb989157bdf4a43eaa8596fdb09df60d114ee" + integrity sha512-6U1pmNZcKLuOWiWRML8Raf9zSEuUCMlsOye82niyF6I0rpPgYo5UFghAAbGISDsyqzM1B2L4BgJ6XrCk/dJptg== + dependencies: + "@lexical/utils" "0.13.1" + +"@lexical/mark@0.13.1": + version "0.13.1" + resolved "https://registry.yarnpkg.com/@lexical/mark/-/mark-0.13.1.tgz#084bb49a8bc1c5c5a4ed5c5d4a20c98ea85ec8b1" + integrity sha512-dW27PW8wWDOKFqXTBUuUfV+umU0KfwvXGkPUAxRJrvwUWk5RKaS48LhgbNlQ5BfT84Q8dSiQzvbaa6T40t9a3A== + dependencies: + "@lexical/utils" "0.13.1" + +"@lexical/markdown@0.13.1": + version "0.13.1" + resolved "https://registry.yarnpkg.com/@lexical/markdown/-/markdown-0.13.1.tgz#1fd2efcacff4ce733682a8161a3f3d78dba37503" + integrity sha512-6tbdme2h5Zy/M88loVQVH5G0Nt7VMR9UUkyiSaicyBRDOU2OHacaXEp+KSS/XuF+d7TA+v/SzyDq8HS77cO1wA== + dependencies: + "@lexical/code" "0.13.1" + "@lexical/link" "0.13.1" + "@lexical/list" "0.13.1" + "@lexical/rich-text" "0.13.1" + "@lexical/text" "0.13.1" + "@lexical/utils" "0.13.1" + +"@lexical/offset@0.13.1": + version "0.13.1" + resolved "https://registry.yarnpkg.com/@lexical/offset/-/offset-0.13.1.tgz#f37417822aef3dc81580d4abb96e43ba9d547225" + integrity sha512-j/RZcztJ7dyTrfA2+C3yXDzWDXV+XmMpD5BYeQCEApaHvlo20PHt1BISk7RcrnQW8PdzGvpKblRWf//c08LS9w== + +"@lexical/overflow@0.13.1": + version "0.13.1" + resolved "https://registry.yarnpkg.com/@lexical/overflow/-/overflow-0.13.1.tgz#42c036dc3ad3eb929fda5aa0a00a725b74f72669" + integrity sha512-Uw34j+qG2UJRCIR+bykfFMduFk7Pc4r/kNt8N1rjxGuGXAsreTVch1iOhu7Ev6tJgkURsduKuaJCAi7iHnKl7g== + +"@lexical/plain-text@0.13.1": + version "0.13.1" + resolved "https://registry.yarnpkg.com/@lexical/plain-text/-/plain-text-0.13.1.tgz#e7e713029443c30facce27b34836bf604cf92c0f" + integrity sha512-4j5KAsMKUvJ8LhVDSS4zczbYXzdfmgYSAVhmqpSnJtud425Nk0TAfpUBLFoivxZB7KMoT1LGWQZvd47IvJPvtA== + +"@lexical/react@0.13.1": + version "0.13.1" + resolved "https://registry.yarnpkg.com/@lexical/react/-/react-0.13.1.tgz#6c35bf43e24560d2ca3aa2c6ff607ef37de87bac" + integrity sha512-Sy6EL230KAb0RZsZf1dZrRrc3+rvCDQWltcd8C/cqBUYlxsLYCW9s4f3RB2werngD/PtLYbBB48SYXNkIALITA== + dependencies: + "@lexical/clipboard" "0.13.1" + "@lexical/code" "0.13.1" + "@lexical/dragon" "0.13.1" + "@lexical/hashtag" "0.13.1" + "@lexical/history" "0.13.1" + "@lexical/link" "0.13.1" + "@lexical/list" "0.13.1" + "@lexical/mark" "0.13.1" + "@lexical/markdown" "0.13.1" + "@lexical/overflow" "0.13.1" + "@lexical/plain-text" "0.13.1" + "@lexical/rich-text" "0.13.1" + "@lexical/selection" "0.13.1" + "@lexical/table" "0.13.1" + "@lexical/text" "0.13.1" + "@lexical/utils" "0.13.1" + "@lexical/yjs" "0.13.1" + react-error-boundary "^3.1.4" + +"@lexical/rich-text@0.13.1": + version "0.13.1" + resolved "https://registry.yarnpkg.com/@lexical/rich-text/-/rich-text-0.13.1.tgz#8251e81a3985a4d76bef027cf6c0dc90c661e4ec" + integrity sha512-HliB9Ync06mv9DBg/5j0lIsTJp+exLHlaLJe+n8Zq1QNTzZzu2LsIT/Crquk50In7K/cjtlaQ/d5RB0LkjMHYg== + +"@lexical/selection@0.13.1": + version "0.13.1" + resolved "https://registry.yarnpkg.com/@lexical/selection/-/selection-0.13.1.tgz#466d7cd0ee1b04680bd949112f1f5cb6a6618efa" + integrity sha512-Kt9eSwjxPznj7yzIYipu9yYEgmRJhHiq3DNxHRxInYcZJWWNNHum2xKyxwwcN8QYBBzgfPegfM/geqQEJSV1lQ== + +"@lexical/table@0.13.1": + version "0.13.1" + resolved "https://registry.yarnpkg.com/@lexical/table/-/table-0.13.1.tgz#814d3b8a2afb821aff151c92cce831809f9d67a1" + integrity sha512-VQzgkfkEmnvn6C64O/kvl0HI3bFoBh3WA/U67ALw+DS11Mb5CKjbt0Gzm/258/reIxNMpshjjicpWMv9Miwauw== + dependencies: + "@lexical/utils" "0.13.1" + +"@lexical/text@0.13.1": + version "0.13.1" + resolved "https://registry.yarnpkg.com/@lexical/text/-/text-0.13.1.tgz#12104d42da7a707a19853679f3a88e8ed6ce8084" + integrity sha512-NYy3TZKt3qzReDwN2Rr5RxyFlg84JjXP2JQGMrXSSN7wYe73ysQIU6PqdVrz4iZkP+w34F3pl55dJ24ei3An9w== + +"@lexical/utils@0.13.1": + version "0.13.1" + resolved "https://registry.yarnpkg.com/@lexical/utils/-/utils-0.13.1.tgz#f2a72f71c859933781294830b38b25b5b33122a9" + integrity sha512-AtQQKzYymkbOaQxaBXjRBS8IPxF9zWQnqwHTUTrJqJ4hX71aIQd/thqZbfQETAFJfC8pNBZw5zpxN6yPHk23dQ== + dependencies: + "@lexical/list" "0.13.1" + "@lexical/selection" "0.13.1" + "@lexical/table" "0.13.1" + +"@lexical/yjs@0.13.1": + version "0.13.1" + resolved "https://registry.yarnpkg.com/@lexical/yjs/-/yjs-0.13.1.tgz#2a71ae3c4b3cc5c660bbe66d537eb0cbf3c7c1b6" + integrity sha512-4GbqQM+PwNTV59AZoNrfTe/0rLjs+cX6Y6yAdZSRPBwr5L3JzYeU1TTcFCVQTtsE7KF8ddVP8sD7w9pi8rOWLA== + dependencies: + "@lexical/offset" "0.13.1" + "@monaco-editor/loader@^1.3.3": version "1.4.0" resolved "https://registry.yarnpkg.com/@monaco-editor/loader/-/loader-1.4.0.tgz#f08227057331ec890fa1e903912a5b711a2ad558" @@ -1575,6 +1735,32 @@ resolved "https://registry.yarnpkg.com/@payloadcms/plugin-seo/-/plugin-seo-1.0.15.tgz#ca794897d1e8c3291a8dd74339b7f28f10bba815" integrity sha512-7nU0DD3UZOOHsV2UIkOWL2JNCX+u1WNbEvZOiGpO6lB6YekuVIMqxHKbTdVR73UeW44lApvS9LTgif3XLQ5HDA== +"@payloadcms/richtext-lexical@^0.11.3": + version "0.11.3" + resolved "https://registry.yarnpkg.com/@payloadcms/richtext-lexical/-/richtext-lexical-0.11.3.tgz#0897023a6465f7281e77cce4990c8f073da6a0d4" + integrity sha512-Y1FXtPQKO+6Prkh7PimptERhM02zWgrIcpFEsRHSyldebK3fv51YnuuaBhDtAqtifAXYAxgrSg5dliEZqmaCjw== + dependencies: + "@faceless-ui/modal" "2.0.1" + "@lexical/headless" "0.13.1" + "@lexical/link" "0.13.1" + "@lexical/list" "0.13.1" + "@lexical/mark" "0.13.1" + "@lexical/markdown" "0.13.1" + "@lexical/react" "0.13.1" + "@lexical/rich-text" "0.13.1" + "@lexical/selection" "0.13.1" + "@lexical/utils" "0.13.1" + bson-objectid "2.0.4" + classnames "^2.3.2" + deep-equal "2.2.3" + i18next "22.5.1" + json-schema "^0.4.0" + lexical "0.13.1" + lodash "4.17.21" + react-error-boundary "4.0.12" + react-i18next "11.18.6" + ts-essentials "7.0.3" + "@payloadcms/richtext-slate@^1.0.0": version "1.5.2" resolved "https://registry.yarnpkg.com/@payloadcms/richtext-slate/-/richtext-slate-1.5.2.tgz#3611923b7a1d62882a10b2df3508f98cb8a11dbf" @@ -3196,7 +3382,7 @@ chrome-trace-event@^1.0.2: resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz#05bffd7ff928465093314708c93bdfa9bd1f0f5b" integrity sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ== -classnames@^2.2.5, classnames@^2.2.6, classnames@^2.3.1: +classnames@^2.2.5, classnames@^2.2.6, classnames@^2.3.1, classnames@^2.3.2: version "2.5.1" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b" integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow== @@ -3653,6 +3839,30 @@ deep-equal@2.2.2: which-collection "^1.0.1" which-typed-array "^1.1.9" +deep-equal@2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.2.3.tgz#af89dafb23a396c7da3e862abc0be27cf51d56e1" + integrity sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA== + dependencies: + array-buffer-byte-length "^1.0.0" + call-bind "^1.0.5" + es-get-iterator "^1.1.3" + get-intrinsic "^1.2.2" + is-arguments "^1.1.1" + is-array-buffer "^3.0.2" + is-date-object "^1.0.5" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + isarray "^2.0.5" + object-is "^1.1.5" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.5.1" + side-channel "^1.0.4" + which-boxed-primitive "^1.0.2" + which-collection "^1.0.1" + which-typed-array "^1.1.13" + deep-extend@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" @@ -4672,7 +4882,7 @@ get-caller-file@^2.0.5: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: +get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== @@ -5542,6 +5752,11 @@ json-schema-typed@^7.0.3: resolved "https://registry.yarnpkg.com/json-schema-typed/-/json-schema-typed-7.0.3.tgz#23ff481b8b4eebcd2ca123b4fa0409e66469a2d9" integrity sha512-7DE8mpG+/fVw+dTpjbxnx47TaMnDfOI1jwft9g1VybltZCduyRQPJPvc+zzKY9WPHxhPWczyFuYa6I8Mw4iU5A== +json-schema@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== + json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" @@ -5651,6 +5866,11 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" +lexical@0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/lexical/-/lexical-0.13.1.tgz#0abffe9bc05a7a9da8a6128ea478bf08c11654db" + integrity sha512-jaqRYzVEfBKbX4FwYpd/g+MyOjRaraAel0iQsTrwvx3hyN0bswUZuzb6H6nGlFSjcdrc77wKpyKwoWj4aUd+Bw== + lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" @@ -5762,7 +5982,7 @@ lodash.upperfirst@4.3.1: resolved "https://registry.yarnpkg.com/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz#1365edf431480481ef0d1c68957a5ed99d49f7ce" integrity sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg== -lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4: +lodash@4.17.21, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -7090,6 +7310,11 @@ pretty-error@^4.0.0: lodash "^4.17.20" renderkid "^3.0.0" +prismjs@^1.27.0: + version "1.29.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12" + integrity sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q== + probe-image-size@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/probe-image-size/-/probe-image-size-6.0.0.tgz#4a85b19d5af4e29a8de7d53a9aa036f6fd02f5f4" @@ -7286,6 +7511,20 @@ react-dom@^18.0.0, react-dom@^18.2.0: loose-envify "^1.1.0" scheduler "^0.23.2" +react-error-boundary@4.0.12: + version "4.0.12" + resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-4.0.12.tgz#59f8f1dbc53bbbb34fc384c8db7cf4082cb63e2c" + integrity sha512-kJdxdEYlb7CPC1A0SeUY38cHpjuu6UkvzKiAmqmOFL21VRfMhOcWxTCBgLVCO0VEMh9JhFNcVaXlV4/BTpiwOA== + dependencies: + "@babel/runtime" "^7.12.5" + +react-error-boundary@^3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-3.1.4.tgz#255db92b23197108757a888b01e5b729919abde0" + integrity sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA== + dependencies: + "@babel/runtime" "^7.12.5" + react-fast-compare@^3.0.1, react-fast-compare@^3.1.1: version "3.2.2" resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49" @@ -7488,7 +7727,7 @@ regenerator-runtime@^0.14.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== -regexp.prototype.flags@^1.5.0, regexp.prototype.flags@^1.5.2: +regexp.prototype.flags@^1.5.0, regexp.prototype.flags@^1.5.1, regexp.prototype.flags@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz#138f644a3350f981a858c44f6bb1a61ff59be334" integrity sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw== @@ -8869,7 +9108,7 @@ which-collection@^1.0.1: is-weakmap "^2.0.2" is-weakset "^2.0.3" -which-typed-array@^1.1.14, which-typed-array@^1.1.15, which-typed-array@^1.1.9: +which-typed-array@^1.1.13, which-typed-array@^1.1.14, which-typed-array@^1.1.15, which-typed-array@^1.1.9: version "1.1.15" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== From 1cf2c6d1269f610250f705361339e0f1da07dd4e Mon Sep 17 00:00:00 2001 From: Rui S Date: Thu, 19 Sep 2024 18:16:45 +0100 Subject: [PATCH 2/9] update: add automatic html generation from lexical - publishing now pushes and generates changes directly to html as 'content_html' - updated graphQL schemas to reflect this change --- src/app/_graphql/blogposts.ts | 1 + src/payload/payload-types.ts | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/app/_graphql/blogposts.ts b/src/app/_graphql/blogposts.ts index f8cbd1c..46aab09 100644 --- a/src/app/_graphql/blogposts.ts +++ b/src/app/_graphql/blogposts.ts @@ -28,6 +28,7 @@ export const BLOGPOST = ` featuredImage { ${MEDIA_FIELDS} } + content_html createdAt updatedAt } diff --git a/src/payload/payload-types.ts b/src/payload/payload-types.ts index 31fbb4b..9978826 100644 --- a/src/payload/payload-types.ts +++ b/src/payload/payload-types.ts @@ -227,8 +227,21 @@ export interface Blogpost { title: string; summary: string; content: { + root: { + type: string; + children: { + type: string; + version: number; + [k: string]: unknown; + }[]; + direction: ('ltr' | 'rtl') | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; [k: string]: unknown; - }[]; + }; + content_html?: string | null; featuredImage: string | Media; authors?: (string | Author)[] | null; categories?: (string | Category)[] | null; From 4eb0839879c4df7580204a0cc50d406270ea2508 Mon Sep 17 00:00:00 2001 From: Rui S Date: Thu, 19 Sep 2024 18:17:43 +0100 Subject: [PATCH 3/9] scaffold Blogpost page - created estimateReadTime function; - added richText renderer; - added several components for each block; --- src/app/(pages)/blogposts/[slug]/page.tsx | 48 ++++++---- src/app/_blocks/Blogpost/index.tsx | 19 ++++ .../BlogPostArchiveButton/index.tsx | 15 ++++ src/app/_components/ContentRenderer/index.tsx | 5 ++ src/app/_components/PostSummary/index.tsx | 29 ++++++ src/app/_utilities/estimateReadTime.ts | 7 ++ src/payload/collections/BlogPosts.ts | 88 ++++++++++--------- 7 files changed, 153 insertions(+), 58 deletions(-) create mode 100644 src/app/_blocks/Blogpost/index.tsx create mode 100644 src/app/_components/BlogPostArchiveButton/index.tsx create mode 100644 src/app/_components/ContentRenderer/index.tsx create mode 100644 src/app/_components/PostSummary/index.tsx create mode 100644 src/app/_utilities/estimateReadTime.ts diff --git a/src/app/(pages)/blogposts/[slug]/page.tsx b/src/app/(pages)/blogposts/[slug]/page.tsx index adc881c..f006698 100644 --- a/src/app/(pages)/blogposts/[slug]/page.tsx +++ b/src/app/(pages)/blogposts/[slug]/page.tsx @@ -1,28 +1,40 @@ -import React from 'react' -import { notFound } from 'next/navigation' +import { notFound } from "next/navigation"; +import { fetchDoc } from "../../../_api/fetchDoc"; +import BackButton from "@/app/_components/BackButton"; +import EpisodeFeaturedImage from "@/app/_components/EpisodeFeaturedImage"; +import PostSummary from "@/app/_components/PostSummary"; -import { fetchDoc } from "../../../_api/fetchDoc" +import { getImage } from "@/app/_utilities/getImage"; +import { Blogpost } from "@/payload/payload-types"; -export default async function BlogpostPage({ params: { slug } }) { - let episode = null +import BlogpostContent from "@/app/_blocks/Blogpost"; +import { Subscribe } from "@/app/_blocks/Subscribe"; +import { RecommendedContent } from "@/app/_blocks/RecommendedContent"; - try { - episode = await fetchDoc({ - collection: 'blogposts', - slug, - }) - } catch (err) { - console.error(err) - } +export default async function BlogpostPage({ params: { slug } }) { + const blogpost: Blogpost | null = await fetchDoc({ + collection: "blogposts", + slug, + }); - if (!episode) { - notFound() + if (!blogpost) { + notFound(); } + const { relatedPosts } = blogpost; return (
- hello, world! -
{JSON.stringify(episode, null, 2)}
+
+ {/* Head Block*/} + + +
+
+ {/* Content Block*/} + +
+ +
- ) + ); } diff --git a/src/app/_blocks/Blogpost/index.tsx b/src/app/_blocks/Blogpost/index.tsx new file mode 100644 index 0000000..a142fb7 --- /dev/null +++ b/src/app/_blocks/Blogpost/index.tsx @@ -0,0 +1,19 @@ +import EpisodeFeaturedImage from "@/app/_components/EpisodeFeaturedImage"; +import { getImage } from "@/app/_utilities/getImage"; +import { Blogpost } from "@/payload/payload-types"; +import ContentRenderer from "@/app/_components/ContentRenderer"; + +export default function BlogpostContent({ post }: { post: Blogpost }) { + + const { summary, content_html, featuredImage } = post; + + console.log(featuredImage); + return ( +
+ +
{summary}
+ + +
+ ); +} diff --git a/src/app/_components/BlogPostArchiveButton/index.tsx b/src/app/_components/BlogPostArchiveButton/index.tsx new file mode 100644 index 0000000..134fcd2 --- /dev/null +++ b/src/app/_components/BlogPostArchiveButton/index.tsx @@ -0,0 +1,15 @@ +export default function ArchiveButton({ collection }: { collection: string }) { + + function formatArchiveButton(text: string): string { + // TODO: Extend to format talks-and-roundtables to Talks & Roundtables + // TODO: Extend to fromat case-studies to Case Studies + + return text.charAt(0).toLowerCase() + text.slice(1); + } + + return ( +
+ {formatArchiveButton(collection)} +
+ ) +} diff --git a/src/app/_components/ContentRenderer/index.tsx b/src/app/_components/ContentRenderer/index.tsx new file mode 100644 index 0000000..31797d0 --- /dev/null +++ b/src/app/_components/ContentRenderer/index.tsx @@ -0,0 +1,5 @@ +export default function ContentRenderer({ content_html }: { content_html: string }){ + return ( +
+ ) +} diff --git a/src/app/_components/PostSummary/index.tsx b/src/app/_components/PostSummary/index.tsx new file mode 100644 index 0000000..398628c --- /dev/null +++ b/src/app/_components/PostSummary/index.tsx @@ -0,0 +1,29 @@ +import React from 'react' + +import ArchiveButton from '@/app/_components/BlogPostArchiveButton' +import { estimateReadTime } from '@/app/_utilities/estimateReadTime' +import { formatDateTime } from '@/app/_utilities/formatDateTime' +import { Blogpost } from '@/payload/payload-types' + +export default function PostSummary({ post }: { post: Blogpost }) { + const { title, publishedAt, content, authors } = post + + return ( +
+ {/* Left column */} +
+ +
{title}
+
+ {formatDateTime(publishedAt)} | {estimateReadTime('Placeholder')} +
+
+ + {/* Right column */} +
+

WRITTEN BY

+

(AuthorPill with SocialLinks)

+
+
+ ) +} diff --git a/src/app/_utilities/estimateReadTime.ts b/src/app/_utilities/estimateReadTime.ts new file mode 100644 index 0000000..a5760ac --- /dev/null +++ b/src/app/_utilities/estimateReadTime.ts @@ -0,0 +1,7 @@ +export function estimateReadTime(text: string): string { + const WPM = 250 + const wordCount = text.split(/\s+/).length + const readTimeMinutes = Math.ceil(wordCount / WPM) + + return `${readTimeMinutes} min read` +} diff --git a/src/payload/collections/BlogPosts.ts b/src/payload/collections/BlogPosts.ts index 1c620c0..38d45d2 100644 --- a/src/payload/collections/BlogPosts.ts +++ b/src/payload/collections/BlogPosts.ts @@ -1,14 +1,15 @@ -import type { CollectionConfig } from 'payload/types' +import type { CollectionConfig } from "payload/types"; -import { admins } from '../access/admins' -import { adminsOrPublished } from '../access/adminsOrPublished' -import { slugField } from '../fields/slug' +import { admins } from "../access/admins"; +import { adminsOrPublished } from "../access/adminsOrPublished"; +import { slugField } from "../fields/slug"; +import { HTMLConverterFeature, lexicalEditor, lexicalHTML } from "@payloadcms/richtext-lexical"; export const BlogPosts: CollectionConfig = { - slug: 'blogposts', + slug: "blogposts", admin: { - useAsTitle: 'title', - defaultColumns: ['title', 'slug', 'updatedAt'], + useAsTitle: "title", + defaultColumns: ["title", "slug", "updatedAt"], }, versions: { drafts: true }, access: { @@ -19,83 +20,90 @@ export const BlogPosts: CollectionConfig = { }, fields: [ { - name: 'title', - type: 'text', + name: "title", + type: "text", required: true, }, { - name: 'summary', - type: 'textarea', + name: "summary", + type: "textarea", required: true, maxLength: 250, admin: { description: ({ path, value }) => `${ - typeof value === 'string' ? 250 - value.length : '250' + typeof value === "string" ? 250 - value.length : "250" } characters left (field: ${path})`, }, }, { - name: 'content', - label: 'Content', - type: 'richText', + name: "content", + label: "Content", + type: "richText", required: true, + editor: lexicalEditor({ + features: ({ defaultFeatures }) => [ + ...defaultFeatures, + HTMLConverterFeature({}), + ], + }), }, + lexicalHTML("content", { name: "content_html" }), { - name: 'featuredImage', - label: 'Featured Image', - type: 'upload', - relationTo: 'media', + name: "featuredImage", + label: "Featured Image", + type: "upload", + relationTo: "media", required: true, admin: { - position: 'sidebar', + position: "sidebar", }, }, { - name: 'authors', - type: 'relationship', - relationTo: 'authors', + name: "authors", + type: "relationship", + relationTo: "authors", hasMany: true, admin: { - position: 'sidebar', + position: "sidebar", }, }, { - name: 'categories', - label: 'Categories', - type: 'relationship', - relationTo: 'categories', + name: "categories", + label: "Categories", + type: "relationship", + relationTo: "categories", hasMany: true, admin: { - position: 'sidebar', + position: "sidebar", }, }, { - name: 'relatedPosts', - type: 'relationship', - relationTo: 'blogposts', + name: "relatedPosts", + type: "relationship", + relationTo: "blogposts", hasMany: true, }, { - name: 'publishedAt', - type: 'date', + name: "publishedAt", + type: "date", admin: { - position: 'sidebar', + position: "sidebar", date: { - pickerAppearance: 'dayAndTime', + pickerAppearance: "dayAndTime", }, }, hooks: { beforeChange: [ ({ siblingData, value }) => { - if (siblingData._status === 'published' && !value) { - return new Date() + if (siblingData._status === "published" && !value) { + return new Date(); } - return value + return value; }, ], }, }, slugField(), ], -} +}; From ed0c3980778482c0a69ed2687fc37da79bdb080d Mon Sep 17 00:00:00 2001 From: Rui S Date: Fri, 20 Sep 2024 10:05:32 +0100 Subject: [PATCH 4/9] update: add DOMpurify to ContentRenderer - added DOMpurify to sanitize HTML to prevent potential XSS vulnerabilities --- package.json | 1 + src/app/_components/ContentRenderer/index.tsx | 11 +++++++---- yarn.lock | 5 +++++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 398ecfe..31eaa5a 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "@payloadcms/richtext-lexical": "^0.11.3", "@payloadcms/richtext-slate": "^1.0.0", "cross-env": "^7.0.3", + "dompurify": "^3.1.6", "dotenv": "^8.2.0", "escape-html": "^1.0.3", "express": "^4.19.2", diff --git a/src/app/_components/ContentRenderer/index.tsx b/src/app/_components/ContentRenderer/index.tsx index 31797d0..9268627 100644 --- a/src/app/_components/ContentRenderer/index.tsx +++ b/src/app/_components/ContentRenderer/index.tsx @@ -1,5 +1,8 @@ -export default function ContentRenderer({ content_html }: { content_html: string }){ - return ( -
- ) +import DOMpurify from 'dompurify' + +export default function ContentRenderer({ content_html }: { content_html: string }) { + // Sanitize HTML content to prevent XSS vulnerabilities. + const sanitizedContent = DOMpurify.sanitize(content_html) + + return
} diff --git a/yarn.lock b/yarn.lock index 2e130cd..b3cc709 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3988,6 +3988,11 @@ domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1: dependencies: domelementtype "^2.2.0" +dompurify@^3.1.6: + version "3.1.6" + resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.1.6.tgz#43c714a94c6a7b8801850f82e756685300a027e2" + integrity sha512-cTOAhc36AalkjtBpfG6O8JimdTMWNXjiePT2xQH/ppBGi/4uIpmj8eKyIkMJErXWARyINV/sB38yf8JCLF5pbQ== + domutils@^2.5.2, domutils@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" From 6921ee5e33df19f3f381b91954dc6918e459468d Mon Sep 17 00:00:00 2001 From: Rui S Date: Fri, 20 Sep 2024 17:15:27 +0100 Subject: [PATCH 5/9] update to isomorphic-dompurify - changed to isomorphic-dompurify package, which contains wrappers to enable DOMPurify on server --- package.json | 2 +- src/app/_components/ContentRenderer/index.tsx | 2 +- yarn.lock | 265 +++++++++++++++++- 3 files changed, 263 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 31eaa5a..7cbf071 100644 --- a/package.json +++ b/package.json @@ -30,10 +30,10 @@ "@payloadcms/richtext-lexical": "^0.11.3", "@payloadcms/richtext-slate": "^1.0.0", "cross-env": "^7.0.3", - "dompurify": "^3.1.6", "dotenv": "^8.2.0", "escape-html": "^1.0.3", "express": "^4.19.2", + "isomorphic-dompurify": "^2.15.0", "next": "13.5.2", "payload": "^2.0.0", "payload-admin-bar": "^1.0.6", diff --git a/src/app/_components/ContentRenderer/index.tsx b/src/app/_components/ContentRenderer/index.tsx index 9268627..6b98044 100644 --- a/src/app/_components/ContentRenderer/index.tsx +++ b/src/app/_components/ContentRenderer/index.tsx @@ -1,4 +1,4 @@ -import DOMpurify from 'dompurify' +import DOMpurify from 'isomorphic-dompurify' export default function ContentRenderer({ content_html }: { content_html: string }) { // Sanitize HTML content to prevent XSS vulnerabilities. diff --git a/yarn.lock b/yarn.lock index b3cc709..2b0ff5c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2434,6 +2434,13 @@ dependencies: "@types/node" "*" +"@types/dompurify@^3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@types/dompurify/-/dompurify-3.0.5.tgz#02069a2fcb89a163bacf1a788f73cb415dd75cb7" + integrity sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg== + dependencies: + "@types/trusted-types" "*" + "@types/escape-html@^1.0.2": version "1.0.4" resolved "https://registry.yarnpkg.com/@types/escape-html/-/escape-html-1.0.4.tgz#dc7c166b76c7b03b27e32f80edf01d91eb5d9af2" @@ -2582,6 +2589,11 @@ "@types/node" "*" "@types/send" "*" +"@types/trusted-types@*": + version "2.0.7" + resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11" + integrity sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw== + "@types/webidl-conversions@*": version "7.0.3" resolved "https://registry.yarnpkg.com/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz#1306dbfa53768bcbcfc95a1c8cde367975581859" @@ -2869,6 +2881,13 @@ acorn@^8.0.4, acorn@^8.11.0, acorn@^8.4.1, acorn@^8.7.1, acorn@^8.8.2, acorn@^8. resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== +agent-base@^7.0.2, agent-base@^7.1.0: + version "7.1.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.1.tgz#bdbded7dfb096b751a2a087eeeb9664725b2e317" + integrity sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA== + dependencies: + debug "^4.3.4" + ajv-formats@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" @@ -3040,6 +3059,11 @@ arraybuffer.prototype.slice@^1.0.3: is-array-buffer "^3.0.4" is-shared-array-buffer "^1.0.2" +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + atomic-sleep@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" @@ -3478,6 +3502,13 @@ colorette@^2.0.10, colorette@^2.0.14, colorette@^2.0.7: resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + commander@^2.20.0, commander@^2.20.3: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -3706,6 +3737,13 @@ cssfilter@0.0.10: resolved "https://registry.yarnpkg.com/cssfilter/-/cssfilter-0.0.10.tgz#c6d2672632a2e5c83e013e6864a42ce8defd20ae" integrity sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw== +cssstyle@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-4.1.0.tgz#161faee382af1bafadb6d3867a92a19bcb4aea70" + integrity sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA== + dependencies: + rrweb-cssom "^0.7.1" + csstype@^3.0.2: version "3.1.3" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" @@ -3724,6 +3762,14 @@ data-uri-to-buffer@^4.0.0: resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e" integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A== +data-urls@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-5.0.0.tgz#2f76906bce1824429ffecb6920f45a0b30f00dde" + integrity sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg== + dependencies: + whatwg-mimetype "^4.0.0" + whatwg-url "^14.0.0" + data-view-buffer@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.1.tgz#8ea6326efec17a2e42620696e671d7d5a8bc66b2" @@ -3794,7 +3840,7 @@ debug@3.1.0: dependencies: ms "2.0.0" -debug@4.x, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: +debug@4, debug@4.x, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: version "4.3.7" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== @@ -3808,6 +3854,11 @@ debug@^3.2.6, debug@^3.2.7: dependencies: ms "^2.1.1" +decimal.js@^10.4.3: + version "10.4.3" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" + integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== + decompress-response@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" @@ -3896,6 +3947,11 @@ define-properties@^1.2.0, define-properties@^1.2.1: has-property-descriptors "^1.0.0" object-keys "^1.1.1" +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + depd@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" @@ -4089,6 +4145,11 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== +entities@^4.4.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + env-paths@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" @@ -4811,6 +4872,15 @@ foreground-child@^3.1.0: cross-spawn "^7.0.0" signal-exit "^4.0.1" +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + formdata-polyfill@^4.0.10: version "4.0.10" resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" @@ -5185,6 +5255,13 @@ homedir-polyfill@^1.0.1: dependencies: parse-passwd "^1.0.0" +html-encoding-sniffer@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz#696df529a7cfd82446369dc5193e590a3735b448" + integrity sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ== + dependencies: + whatwg-encoding "^3.1.1" + html-entities@^2.1.0: version "2.5.2" resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.5.2.tgz#201a3cf95d3a15be7099521620d19dfb4f65359f" @@ -5258,11 +5335,27 @@ http-errors@2.0.0: statuses "2.0.1" toidentifier "1.0.1" +http-proxy-agent@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" + integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig== + dependencies: + agent-base "^7.1.0" + debug "^4.3.4" + http-status@1.6.2: version "1.6.2" resolved "https://registry.yarnpkg.com/http-status/-/http-status-1.6.2.tgz#6dc05188a9856d67d96e48e8b4fd645c719ce82a" integrity sha512-oUExvfNckrpTpDazph7kNG8sQi5au3BeTo0idaZFXEhTaJKu7GNJCLHI0rYY2wljm548MSTM+Ljj/c6anqu2zQ== +https-proxy-agent@^7.0.5: + version "7.0.5" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz#9e8b5013873299e11fab6fd548405da2d6c602b2" + integrity sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw== + dependencies: + agent-base "^7.0.2" + debug "4" + i18next-browser-languagedetector@6.1.8: version "6.1.8" resolved "https://registry.yarnpkg.com/i18next-browser-languagedetector/-/i18next-browser-languagedetector-6.1.8.tgz#8e9c61b32a4dfe9b959b38bc9d2a8b95f799b27c" @@ -5289,6 +5382,13 @@ iconv-lite@0.4.24, iconv-lite@^0.4.4: dependencies: safer-buffer ">= 2.1.2 < 3" +iconv-lite@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + icss-utils@^5.0.0, icss-utils@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" @@ -5540,6 +5640,11 @@ is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" +is-potential-custom-element-name@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" + integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== + is-promise@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" @@ -5636,6 +5741,15 @@ isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== +isomorphic-dompurify@^2.15.0: + version "2.15.0" + resolved "https://registry.yarnpkg.com/isomorphic-dompurify/-/isomorphic-dompurify-2.15.0.tgz#d3d35fe8cab700c4cf3c065da3dc86d508161502" + integrity sha512-RDHlyeVmwEDAPZuX1VaaBzSn9RrsfvswxH7faEQK9cTHC1dXeNuK6ElUeSr7locFyeLguut8ASfhQWxHB4Ttug== + dependencies: + "@types/dompurify" "^3.0.5" + dompurify "^3.1.6" + jsdom "^25.0.0" + isomorphic-fetch@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz#0267b005049046d2421207215d45d6a262b8b8b4" @@ -5708,6 +5822,33 @@ jsbn@1.1.0: resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-1.1.0.tgz#b01307cb29b618a1ed26ec79e911f803c4da0040" integrity sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A== +jsdom@^25.0.0: + version "25.0.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-25.0.0.tgz#d1612b4ddab85af56821b2f731e15faae135f4e1" + integrity sha512-OhoFVT59T7aEq75TVw9xxEfkXgacpqAhQaYgP9y/fDqWQCMB/b1H66RfmPm/MaeaAIU9nDwMOVTlPN51+ao6CQ== + dependencies: + cssstyle "^4.0.1" + data-urls "^5.0.0" + decimal.js "^10.4.3" + form-data "^4.0.0" + html-encoding-sniffer "^4.0.0" + http-proxy-agent "^7.0.2" + https-proxy-agent "^7.0.5" + is-potential-custom-element-name "^1.0.1" + nwsapi "^2.2.12" + parse5 "^7.1.2" + rrweb-cssom "^0.7.1" + saxes "^6.0.0" + symbol-tree "^3.2.4" + tough-cookie "^4.1.4" + w3c-xmlserializer "^5.0.0" + webidl-conversions "^7.0.0" + whatwg-encoding "^3.1.1" + whatwg-mimetype "^4.0.0" + whatwg-url "^14.0.0" + ws "^8.18.0" + xml-name-validator "^5.0.0" + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -6121,7 +6262,7 @@ mime-db@1.52.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.53.0.tgz#3cb63cd820fc29896d9d4e8c32ab4fcd74ccb447" integrity sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg== -mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.24, mime-types@~2.1.34: +mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -6445,6 +6586,11 @@ nth-check@^2.0.1: dependencies: boolbase "^1.0.0" +nwsapi@^2.2.12: + version "2.2.12" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.12.tgz#fb6af5c0ec35b27b4581eb3bbad34ec9e5c696f8" + integrity sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w== + object-assign@^4.0.1, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -6615,6 +6761,13 @@ parse-passwd@^1.0.0: resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" integrity sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q== +parse5@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32" + integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw== + dependencies: + entities "^4.4.0" + parseurl@~1.3.2, parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -7369,6 +7522,11 @@ proxy-addr@~2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" +psl@^1.1.33: + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== + pstree.remy@^1.1.8: version "1.1.8" resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" @@ -7382,7 +7540,7 @@ pump@^3.0.0: end-of-stream "^1.1.0" once "^1.3.1" -punycode@^2.1.0, punycode@^2.1.1: +punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== @@ -7420,6 +7578,11 @@ qs@~6.4.0: resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.1.tgz#2bad97710a5b661c366b378b1e3a44a592ff45e6" integrity sha512-LQy1Q1fcva/UsnP/6Iaa4lVeM49WiOitu2T4hZCyA/elLKu37L99qcBJk4VCCk+rdLvnMzfKyiN3SZTqdAZGSQ== +querystringify@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== + queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -7768,6 +7931,11 @@ require-from-string@^2.0.2: resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + resolve-cwd@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" @@ -7824,6 +7992,11 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" +rrweb-cssom@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz#c73451a484b86dd7cfb1e0b2898df4b703183e4b" + integrity sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg== + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -7865,7 +8038,7 @@ safe-stable-stringify@^2.3.1: resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd" integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA== -"safer-buffer@>= 2.1.2 < 3": +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -7899,6 +8072,13 @@ sax@^1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f" integrity sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg== +saxes@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-6.0.0.tgz#fe5b4a4768df4f14a201b1ba6a65c1f3d9988cc5" + integrity sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA== + dependencies: + xmlchars "^2.2.0" + scheduler@0.23.0: version "0.23.0" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" @@ -8469,6 +8649,11 @@ swc-minify-webpack-plugin@^2.1.0: resolved "https://registry.yarnpkg.com/swc-minify-webpack-plugin/-/swc-minify-webpack-plugin-2.1.3.tgz#45ef7376f65a995bccbce5c6c585f801e2f7ce0d" integrity sha512-92/2qgTG663L8tHydvr1qevJ40x1qsve2feQoe/W2CD5uh8IagCVsUV2CfN8ik8erN+6IXR+xmOy9W+Z+m6z+w== +symbol-tree@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== + tabbable@^5.3.3: version "5.3.3" resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-5.3.3.tgz#aac0ff88c73b22d6c3c5a50b1586310006b47fbf" @@ -8651,6 +8836,16 @@ touch@^3.1.0: resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.1.tgz#097a23d7b161476435e5c1344a95c0f75b4a5694" integrity sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA== +tough-cookie@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.4.tgz#945f1461b45b5a8c76821c33ea49c3ac192c1b36" + integrity sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag== + dependencies: + psl "^1.1.33" + punycode "^2.1.1" + universalify "^0.2.0" + url-parse "^1.5.3" + tr46@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/tr46/-/tr46-3.0.0.tgz#555c4e297a950617e8eeddef633c87d4d9d6cbf9" @@ -8658,6 +8853,13 @@ tr46@^3.0.0: dependencies: punycode "^2.1.1" +tr46@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-5.0.0.tgz#3b46d583613ec7283020d79019f1335723801cec" + integrity sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g== + dependencies: + punycode "^2.3.1" + tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" @@ -8827,6 +9029,11 @@ unfetch@^4.2.0: resolved "https://registry.yarnpkg.com/unfetch/-/unfetch-4.2.0.tgz#7e21b0ef7d363d8d9af0fb929a5555f6ef97a3be" integrity sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA== +universalify@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" + integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== + universalify@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" @@ -8866,6 +9073,14 @@ url-loader@4.1.1: mime-types "^2.1.27" schema-utils "^3.0.0" +url-parse@^1.5.3: + version "1.5.10" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + use-context-selector@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/use-context-selector/-/use-context-selector-1.4.1.tgz#eb96279965846b72915d7f899b8e6ef1d768b0ae" @@ -8926,6 +9141,13 @@ void-elements@3.1.0: resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09" integrity sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w== +w3c-xmlserializer@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz#f925ba26855158594d907313cedd1476c5967f6c" + integrity sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA== + dependencies: + xml-name-validator "^5.0.0" + warning@^4.0.2: version "4.0.3" resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" @@ -9071,11 +9293,23 @@ webpack@^5.78.0: watchpack "^2.4.1" webpack-sources "^3.2.3" +whatwg-encoding@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz#d0f4ef769905d426e1688f3e34381a99b60b76e5" + integrity sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ== + dependencies: + iconv-lite "0.6.3" + whatwg-fetch@^3.4.1: version "3.6.20" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz#580ce6d791facec91d37c72890995a0b48d31c70" integrity sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg== +whatwg-mimetype@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz#bc1bf94a985dc50388d54a9258ac405c3ca2fc0a" + integrity sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg== + whatwg-url@^11.0.0: version "11.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-11.0.0.tgz#0a849eebb5faf2119b901bb76fd795c2848d4018" @@ -9084,6 +9318,14 @@ whatwg-url@^11.0.0: tr46 "^3.0.0" webidl-conversions "^7.0.0" +whatwg-url@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-14.0.0.tgz#00baaa7fd198744910c4b1ef68378f2200e4ceb6" + integrity sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw== + dependencies: + tr46 "^5.0.0" + webidl-conversions "^7.0.0" + whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" @@ -9185,6 +9427,21 @@ ws@^7.3.1: resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== +ws@^8.18.0: + version "8.18.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" + integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== + +xml-name-validator@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-5.0.0.tgz#82be9b957f7afdacf961e5980f1bf227c0bf7673" + integrity sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg== + +xmlchars@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== + xss@^1.0.6: version "1.0.15" resolved "https://registry.yarnpkg.com/xss/-/xss-1.0.15.tgz#96a0e13886f0661063028b410ed1b18670f4e59a" From 04ec24623e6180f63fb1fc62dda92debc6b86b9a Mon Sep 17 00:00:00 2001 From: Rui S Date: Fri, 20 Sep 2024 17:18:01 +0100 Subject: [PATCH 6/9] fix: graphQL query - $slug var was missing --- src/app/_graphql/blogposts.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/_graphql/blogposts.ts b/src/app/_graphql/blogposts.ts index 46aab09..b05ad09 100644 --- a/src/app/_graphql/blogposts.ts +++ b/src/app/_graphql/blogposts.ts @@ -1,8 +1,8 @@ import { MEDIA_FIELDS } from "./media" export const BLOGPOST = ` - query Blogpost { - Blogposts { + query Blogpost ($slug: String) { + Blogposts(where: { slug: { equals: $slug }}) { docs { id title From a5ce6f1ef34c6c1e34dc8348b3e1114161eda8ad Mon Sep 17 00:00:00 2001 From: Rui S Date: Fri, 20 Sep 2024 17:30:58 +0100 Subject: [PATCH 7/9] update: add AuthorPill to right column --- src/app/_components/PostSummary/index.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/app/_components/PostSummary/index.tsx b/src/app/_components/PostSummary/index.tsx index 398628c..a39e723 100644 --- a/src/app/_components/PostSummary/index.tsx +++ b/src/app/_components/PostSummary/index.tsx @@ -4,10 +4,12 @@ import ArchiveButton from '@/app/_components/BlogPostArchiveButton' import { estimateReadTime } from '@/app/_utilities/estimateReadTime' import { formatDateTime } from '@/app/_utilities/formatDateTime' import { Blogpost } from '@/payload/payload-types' +import AuthorPill from "@/app/_components/AuthorPill"; export default function PostSummary({ post }: { post: Blogpost }) { const { title, publishedAt, content, authors } = post + return (
{/* Left column */} @@ -17,12 +19,14 @@ export default function PostSummary({ post }: { post: Blogpost }) {
{formatDateTime(publishedAt)} | {estimateReadTime('Placeholder')}
+
{/* Right column */}

WRITTEN BY

-

(AuthorPill with SocialLinks)

+ +
) From 2393b0beb668bc965fb52be5df5e0606d7a5a720 Mon Sep 17 00:00:00 2001 From: Rui S Date: Fri, 20 Sep 2024 17:41:04 +0100 Subject: [PATCH 8/9] scaffold blogpost page --- src/app/(pages)/blogposts/[slug]/page.tsx | 36 +++++++++++++++++++---- src/app/_blocks/Blogpost/index.tsx | 9 +++--- src/app/_graphql/blogposts.ts | 3 ++ 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/src/app/(pages)/blogposts/[slug]/page.tsx b/src/app/(pages)/blogposts/[slug]/page.tsx index f006698..c079913 100644 --- a/src/app/(pages)/blogposts/[slug]/page.tsx +++ b/src/app/(pages)/blogposts/[slug]/page.tsx @@ -10,6 +10,9 @@ import { Blogpost } from "@/payload/payload-types"; import BlogpostContent from "@/app/_blocks/Blogpost"; import { Subscribe } from "@/app/_blocks/Subscribe"; import { RecommendedContent } from "@/app/_blocks/RecommendedContent"; +import Categories from "@/payload/collections/Categories"; +import CategoryPill from "@/app/_components/CategoryPill"; +import ContentCard from "@/app/_components/ContentCard"; export default async function BlogpostPage({ params: { slug } }) { const blogpost: Blogpost | null = await fetchDoc({ @@ -20,18 +23,41 @@ export default async function BlogpostPage({ params: { slug } }) { if (!blogpost) { notFound(); } - + console.log(blogpost.content_html); const { relatedPosts } = blogpost; return (
-
+
{/* Head Block*/}
-
- {/* Content Block*/} - +
+ {/* Left column: Navigation */} +
+

Table of contents block

+
+ + {/* Middle column: Content block */} +
+ +
+ + {/* Right column: Social sharing & recommended */} +
+
+

Share block goes here

+

SocialMedia block with links

+
+
+

Category block

+
+
+

Recommended Block

+ + +
+
diff --git a/src/app/_blocks/Blogpost/index.tsx b/src/app/_blocks/Blogpost/index.tsx index a142fb7..9fe7ffc 100644 --- a/src/app/_blocks/Blogpost/index.tsx +++ b/src/app/_blocks/Blogpost/index.tsx @@ -1,18 +1,17 @@ import EpisodeFeaturedImage from "@/app/_components/EpisodeFeaturedImage"; -import { getImage } from "@/app/_utilities/getImage"; import { Blogpost } from "@/payload/payload-types"; -import ContentRenderer from "@/app/_components/ContentRenderer"; +import DOMPurify from "isomorphic-dompurify"; export default function BlogpostContent({ post }: { post: Blogpost }) { const { summary, content_html, featuredImage } = post; + const sanitizedContent = DOMPurify.sanitize(content_html); - console.log(featuredImage); return (
- +
{summary}
- +
); diff --git a/src/app/_graphql/blogposts.ts b/src/app/_graphql/blogposts.ts index b05ad09..16ed445 100644 --- a/src/app/_graphql/blogposts.ts +++ b/src/app/_graphql/blogposts.ts @@ -15,6 +15,9 @@ export const BLOGPOST = ` authors { name role + featuredImage { + ${MEDIA_FIELDS} + } } categories { title From 498dec70b6a5447868f6dc8b528202cd1eefe971 Mon Sep 17 00:00:00 2001 From: Rui S Date: Fri, 20 Sep 2024 17:56:33 +0100 Subject: [PATCH 9/9] linting --- src/app/(pages)/[slug]/page.tsx | 2 +- src/app/(pages)/authors/[slug]/page.tsx | 2 +- src/app/(pages)/blogposts/[slug]/page.tsx | 67 ++++++++------ src/app/(pages)/case-studies/[slug]/page.tsx | 2 +- .../(pages)/podcast-episodes/[slug]/page.tsx | 2 +- .../talks-and-roundtables/[slug]/page.tsx | 3 +- src/app/_blocks/AuthorContentGrid/index.tsx | 3 +- src/app/_blocks/Blogpost/index.tsx | 17 ++-- src/app/_blocks/EpisodeHead/index.tsx | 2 +- src/app/_components/AuthorPill/index.tsx | 11 ++- src/app/_components/AuthorSummary/index.tsx | 2 +- src/app/_components/Authors/index.tsx | 7 +- .../BlogPostArchiveButton/index.tsx | 3 +- src/app/_components/Container/index.tsx | 12 +-- src/app/_components/ContentCard/index.tsx | 2 +- src/app/_components/FeaturedImage/index.tsx | 1 - src/app/_components/PostSummary/index.tsx | 17 ++-- src/app/_graphql/blogposts.ts | 2 +- src/app/_graphql/contentFromAuthor.ts | 2 +- src/app/_utilities/useEpisodeDuration.ts | 2 +- src/payload/collections/BlogPosts.ts | 89 +++++++++---------- src/payload/payload.config.ts | 6 +- src/server.ts | 1 - 23 files changed, 129 insertions(+), 128 deletions(-) diff --git a/src/app/(pages)/[slug]/page.tsx b/src/app/(pages)/[slug]/page.tsx index 2892c82..441ed51 100644 --- a/src/app/(pages)/[slug]/page.tsx +++ b/src/app/(pages)/[slug]/page.tsx @@ -4,12 +4,12 @@ import { draftMode } from 'next/headers' import { notFound } from 'next/navigation' import { Page } from '../../../payload/payload-types' -import { staticHome } from './staticHome' import { fetchDoc } from '../../_api/fetchDoc' import { fetchDocs } from '../../_api/fetchDocs' import { Blocks } from '../../_components/Blocks' import { Hero } from '../../_components/Hero' import { generateMeta } from '../../_utilities/generateMeta' +import { staticHome } from './staticHome' // Payload Cloud caches all files through Cloudflare, so we don't need Next.js to cache them as well // This means that we can turn off Next.js data caching and instead rely solely on the Cloudflare CDN diff --git a/src/app/(pages)/authors/[slug]/page.tsx b/src/app/(pages)/authors/[slug]/page.tsx index 66c2135..dd49309 100644 --- a/src/app/(pages)/authors/[slug]/page.tsx +++ b/src/app/(pages)/authors/[slug]/page.tsx @@ -8,7 +8,7 @@ import BackButton from '../../../_components/BackButton' export default async function ContributorPage({ params: { slug } }) { // TODO: update fetchDoc to include error handling instead of making it on-page - const author = await fetchDoc({collection: 'authors', slug}) + const author = await fetchDoc({ collection: 'authors', slug }) const contentFromAuthor = await fetchContentFromAuthor({ authorID: author.id }) if (!author) { diff --git a/src/app/(pages)/blogposts/[slug]/page.tsx b/src/app/(pages)/blogposts/[slug]/page.tsx index c079913..70361e1 100644 --- a/src/app/(pages)/blogposts/[slug]/page.tsx +++ b/src/app/(pages)/blogposts/[slug]/page.tsx @@ -1,50 +1,63 @@ -import { notFound } from "next/navigation"; -import { fetchDoc } from "../../../_api/fetchDoc"; -import BackButton from "@/app/_components/BackButton"; -import EpisodeFeaturedImage from "@/app/_components/EpisodeFeaturedImage"; -import PostSummary from "@/app/_components/PostSummary"; +import { notFound } from 'next/navigation' -import { getImage } from "@/app/_utilities/getImage"; -import { Blogpost } from "@/payload/payload-types"; - -import BlogpostContent from "@/app/_blocks/Blogpost"; -import { Subscribe } from "@/app/_blocks/Subscribe"; -import { RecommendedContent } from "@/app/_blocks/RecommendedContent"; -import Categories from "@/payload/collections/Categories"; -import CategoryPill from "@/app/_components/CategoryPill"; -import ContentCard from "@/app/_components/ContentCard"; +import { Blogpost } from '../../../../payload/payload-types' +import { fetchDoc } from '../../../_api/fetchDoc' +import BlogpostContent from '../../../_blocks/Blogpost' +import { RecommendedContent } from '../../../_blocks/RecommendedContent' +import { Subscribe } from '../../../_blocks/Subscribe' +import BackButton from '../../../_components/BackButton' +import ContentCard from '../../../_components/ContentCard' +import PostSummary from '../../../_components/PostSummary' export default async function BlogpostPage({ params: { slug } }) { const blogpost: Blogpost | null = await fetchDoc({ - collection: "blogposts", + collection: 'blogposts', slug, - }); + }) + + // TODO: implement a fetcher for related content to populate related cards if (!blogpost) { - notFound(); + notFound() } - console.log(blogpost.content_html); - const { relatedPosts } = blogpost; + + const { relatedPosts } = blogpost return (
-
+
{/* Head Block*/}
-
+
{/* Left column: Navigation */} -
+

Table of contents block

{/* Middle column: Content block */} -
+
{/* Right column: Social sharing & recommended */} -
+

Share block goes here

SocialMedia block with links

@@ -54,13 +67,13 @@ export default async function BlogpostPage({ params: { slug } }) {

Recommended Block

- - + +
- ); + ) } diff --git a/src/app/(pages)/case-studies/[slug]/page.tsx b/src/app/(pages)/case-studies/[slug]/page.tsx index 596f8ef..226281a 100644 --- a/src/app/(pages)/case-studies/[slug]/page.tsx +++ b/src/app/(pages)/case-studies/[slug]/page.tsx @@ -1,7 +1,7 @@ import React from 'react' import { notFound } from 'next/navigation' -import { fetchDoc } from "../../../_api/fetchDoc" +import { fetchDoc } from '../../../_api/fetchDoc' export default async function CaseStudiesPage({ params: { slug } }) { let content = null diff --git a/src/app/(pages)/podcast-episodes/[slug]/page.tsx b/src/app/(pages)/podcast-episodes/[slug]/page.tsx index 07332ce..5768a52 100644 --- a/src/app/(pages)/podcast-episodes/[slug]/page.tsx +++ b/src/app/(pages)/podcast-episodes/[slug]/page.tsx @@ -2,7 +2,7 @@ import { notFound } from 'next/navigation' import { fetchDoc } from '../../../_api/fetchDoc' import EpisodeContent from '../../../_blocks/EpisodeContent' -import EpisodeHead from '../../../_blocks/EpisodeHead' +import EpisodeHead from '../../../_blocks/EpisodeHead' import { RecommendedContent } from '../../../_blocks/RecommendedContent' import { Subscribe } from '../../../_blocks/Subscribe' diff --git a/src/app/(pages)/talks-and-roundtables/[slug]/page.tsx b/src/app/(pages)/talks-and-roundtables/[slug]/page.tsx index 5648f62..7050fa3 100644 --- a/src/app/(pages)/talks-and-roundtables/[slug]/page.tsx +++ b/src/app/(pages)/talks-and-roundtables/[slug]/page.tsx @@ -1,5 +1,6 @@ import { notFound } from 'next/navigation' -import { fetchDoc } from "../../../_api/fetchDoc" + +import { fetchDoc } from '../../../_api/fetchDoc' export default async function TalksAndRoundTablesPage({ params: { slug } }) { let content = null diff --git a/src/app/_blocks/AuthorContentGrid/index.tsx b/src/app/_blocks/AuthorContentGrid/index.tsx index f4488e9..78b6bd5 100644 --- a/src/app/_blocks/AuthorContentGrid/index.tsx +++ b/src/app/_blocks/AuthorContentGrid/index.tsx @@ -34,8 +34,7 @@ export default function AuthorContentGrid({ content }: AuthorContentGridProps) { >
- )), - )} + )),)}
diff --git a/src/app/_blocks/Blogpost/index.tsx b/src/app/_blocks/Blogpost/index.tsx index 9fe7ffc..2c0059f 100644 --- a/src/app/_blocks/Blogpost/index.tsx +++ b/src/app/_blocks/Blogpost/index.tsx @@ -1,18 +1,17 @@ -import EpisodeFeaturedImage from "@/app/_components/EpisodeFeaturedImage"; -import { Blogpost } from "@/payload/payload-types"; -import DOMPurify from "isomorphic-dompurify"; +import DOMPurify from 'isomorphic-dompurify' -export default function BlogpostContent({ post }: { post: Blogpost }) { +import { Blogpost } from '../../../payload/payload-types' +import EpisodeFeaturedImage from '../../_components/EpisodeFeaturedImage' - const { summary, content_html, featuredImage } = post; - const sanitizedContent = DOMPurify.sanitize(content_html); +export default function BlogpostContent({ post }: { post: Blogpost }) { + const { summary, content_html, featuredImage } = post + const sanitizedContent = DOMPurify.sanitize(content_html) return (
{summary}
-
- +
- ); + ) } diff --git a/src/app/_blocks/EpisodeHead/index.tsx b/src/app/_blocks/EpisodeHead/index.tsx index 6128ba6..bdbb3ea 100644 --- a/src/app/_blocks/EpisodeHead/index.tsx +++ b/src/app/_blocks/EpisodeHead/index.tsx @@ -7,8 +7,8 @@ import ContentTypePill from '../../_components/ContentTypePill' import EpisodeFeaturedImage from '../../_components/EpisodeFeaturedImage' import { formatDateTime } from '../../_utilities/formatDateTime' import { getAudio } from '../../_utilities/getAudio' -import { useEpisodeDuration } from '../../_utilities/useEpisodeDuration' import { getImage } from '../../_utilities/getImage' +import { useEpisodeDuration } from '../../_utilities/useEpisodeDuration' export default function EpisodeHead({ episode }) { const { title, episodeFile, publishedAt, featuredImage } = episode diff --git a/src/app/_components/AuthorPill/index.tsx b/src/app/_components/AuthorPill/index.tsx index bbe5048..2a52ee7 100644 --- a/src/app/_components/AuthorPill/index.tsx +++ b/src/app/_components/AuthorPill/index.tsx @@ -1,13 +1,12 @@ -import { getImage } from "@/app/_utilities/getImage"; +import { getImage } from '@/app/_utilities/getImage' -export default function AuthorPill({author}) { +export default function AuthorPill({ author }) { return ( -
-
- +
+
+ {author.name}
-
) } diff --git a/src/app/_components/AuthorSummary/index.tsx b/src/app/_components/AuthorSummary/index.tsx index 709a909..35394df 100644 --- a/src/app/_components/AuthorSummary/index.tsx +++ b/src/app/_components/AuthorSummary/index.tsx @@ -1,8 +1,8 @@ import React from 'react' +import { Author } from '../../../payload/payload-types' import FeaturedImage from '../FeaturedImage' import SocialLinks from '../SocialLinks' -import { Author } from '../../../payload/payload-types' export default function AuthorSummary({ author }: { author: Author }) { const { name, role, bio, linkedIn, gitHub, medium, x, featuredImage } = author diff --git a/src/app/_components/Authors/index.tsx b/src/app/_components/Authors/index.tsx index fe2f6ed..b5bf02b 100644 --- a/src/app/_components/Authors/index.tsx +++ b/src/app/_components/Authors/index.tsx @@ -1,7 +1,8 @@ -import AuthorPill from "@/app/_components/AuthorPill"; -import React from "react"; +import React from 'react' -export default function Authors({authors}) { +import AuthorPill from '@/app/_components/AuthorPill' + +export default function Authors({ authors }) { return (
diff --git a/src/app/_components/BlogPostArchiveButton/index.tsx b/src/app/_components/BlogPostArchiveButton/index.tsx index 134fcd2..c3846db 100644 --- a/src/app/_components/BlogPostArchiveButton/index.tsx +++ b/src/app/_components/BlogPostArchiveButton/index.tsx @@ -1,10 +1,9 @@ export default function ArchiveButton({ collection }: { collection: string }) { - function formatArchiveButton(text: string): string { // TODO: Extend to format talks-and-roundtables to Talks & Roundtables // TODO: Extend to fromat case-studies to Case Studies - return text.charAt(0).toLowerCase() + text.slice(1); + return text.charAt(0).toLowerCase() + text.slice(1) } return ( diff --git a/src/app/_components/Container/index.tsx b/src/app/_components/Container/index.tsx index 8e41ec1..497ce71 100644 --- a/src/app/_components/Container/index.tsx +++ b/src/app/_components/Container/index.tsx @@ -1,8 +1,10 @@ -import React from "react"; +import React from 'react' export default function Container({ totalArticles, children }) { - return
-
{totalArticles} Articles
- {children} -
+ return ( +
+
{totalArticles} Articles
+ {children} +
+ ) } diff --git a/src/app/_components/ContentCard/index.tsx b/src/app/_components/ContentCard/index.tsx index 923f62c..86b3819 100644 --- a/src/app/_components/ContentCard/index.tsx +++ b/src/app/_components/ContentCard/index.tsx @@ -6,8 +6,8 @@ import { formatDateTime } from '../../_utilities/formatDateTime' import { getImage } from '../../_utilities/getImage' import { toKebabCase } from '../../_utilities/toKebabCase' import Authors from '../Authors' -import EpisodeFeaturedImage from '../EpisodeFeaturedImage' import CategoryPill from '../CategoryPill' +import EpisodeFeaturedImage from '../EpisodeFeaturedImage' interface ContentSummaryProps { contentType: string diff --git a/src/app/_components/FeaturedImage/index.tsx b/src/app/_components/FeaturedImage/index.tsx index d344c66..b42ce75 100644 --- a/src/app/_components/FeaturedImage/index.tsx +++ b/src/app/_components/FeaturedImage/index.tsx @@ -1,7 +1,6 @@ import { getImage } from '../../_utilities/getImage' export default function FeaturedImage({ src }) { - return (
{/* Left column */} @@ -19,14 +16,12 @@ export default function PostSummary({ post }: { post: Blogpost }) {
{formatDateTime(publishedAt)} | {estimateReadTime('Placeholder')}
-
{/* Right column */}

WRITTEN BY

- - +
) diff --git a/src/app/_graphql/blogposts.ts b/src/app/_graphql/blogposts.ts index 16ed445..0e0bb00 100644 --- a/src/app/_graphql/blogposts.ts +++ b/src/app/_graphql/blogposts.ts @@ -1,4 +1,4 @@ -import { MEDIA_FIELDS } from "./media" +import { MEDIA_FIELDS } from './media' export const BLOGPOST = ` query Blogpost ($slug: String) { diff --git a/src/app/_graphql/contentFromAuthor.ts b/src/app/_graphql/contentFromAuthor.ts index 4a1750a..8defc52 100644 --- a/src/app/_graphql/contentFromAuthor.ts +++ b/src/app/_graphql/contentFromAuthor.ts @@ -1,4 +1,4 @@ -import { MEDIA_FIELDS } from "@/app/_graphql/media"; +import { MEDIA_FIELDS } from '@/app/_graphql/media' export const CONTENT_FROM_AUTHOR = ` query GetContent($authorID: JSON!) { diff --git a/src/app/_utilities/useEpisodeDuration.ts b/src/app/_utilities/useEpisodeDuration.ts index da9ed9c..a36539e 100644 --- a/src/app/_utilities/useEpisodeDuration.ts +++ b/src/app/_utilities/useEpisodeDuration.ts @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react' -import { formatEpisodeDuration } from "./formatEpisodeDuration" +import { formatEpisodeDuration } from './formatEpisodeDuration' export function useEpisodeDuration({ src }: { src: string }): string { const [duration, setDuration] = useState(null) diff --git a/src/payload/collections/BlogPosts.ts b/src/payload/collections/BlogPosts.ts index 38d45d2..f801f0d 100644 --- a/src/payload/collections/BlogPosts.ts +++ b/src/payload/collections/BlogPosts.ts @@ -1,15 +1,15 @@ -import type { CollectionConfig } from "payload/types"; +import { HTMLConverterFeature, lexicalEditor, lexicalHTML } from '@payloadcms/richtext-lexical' +import type { CollectionConfig } from 'payload/types' -import { admins } from "../access/admins"; -import { adminsOrPublished } from "../access/adminsOrPublished"; -import { slugField } from "../fields/slug"; -import { HTMLConverterFeature, lexicalEditor, lexicalHTML } from "@payloadcms/richtext-lexical"; +import { admins } from '../access/admins' +import { adminsOrPublished } from '../access/adminsOrPublished' +import { slugField } from '../fields/slug' export const BlogPosts: CollectionConfig = { - slug: "blogposts", + slug: 'blogposts', admin: { - useAsTitle: "title", - defaultColumns: ["title", "slug", "updatedAt"], + useAsTitle: 'title', + defaultColumns: ['title', 'slug', 'updatedAt'], }, versions: { drafts: true }, access: { @@ -20,90 +20,87 @@ export const BlogPosts: CollectionConfig = { }, fields: [ { - name: "title", - type: "text", + name: 'title', + type: 'text', required: true, }, { - name: "summary", - type: "textarea", + name: 'summary', + type: 'textarea', required: true, maxLength: 250, admin: { description: ({ path, value }) => `${ - typeof value === "string" ? 250 - value.length : "250" + typeof value === 'string' ? 250 - value.length : '250' } characters left (field: ${path})`, }, }, { - name: "content", - label: "Content", - type: "richText", + name: 'content', + label: 'Content', + type: 'richText', required: true, editor: lexicalEditor({ - features: ({ defaultFeatures }) => [ - ...defaultFeatures, - HTMLConverterFeature({}), - ], + features: ({ defaultFeatures }) => [...defaultFeatures, HTMLConverterFeature({})], }), }, - lexicalHTML("content", { name: "content_html" }), + lexicalHTML('content', { name: 'content_html' }), { - name: "featuredImage", - label: "Featured Image", - type: "upload", - relationTo: "media", + name: 'featuredImage', + label: 'Featured Image', + type: 'upload', + relationTo: 'media', required: true, admin: { - position: "sidebar", + position: 'sidebar', }, }, { - name: "authors", - type: "relationship", - relationTo: "authors", + name: 'authors', + type: 'relationship', + relationTo: 'authors', hasMany: true, admin: { - position: "sidebar", + position: 'sidebar', }, }, { - name: "categories", - label: "Categories", - type: "relationship", - relationTo: "categories", + name: 'categories', + label: 'Categories', + type: 'relationship', + relationTo: 'categories', hasMany: true, admin: { - position: "sidebar", + position: 'sidebar', }, }, { - name: "relatedPosts", - type: "relationship", - relationTo: "blogposts", + name: 'relatedPosts', + type: 'relationship', + relationTo: 'blogposts', hasMany: true, }, { - name: "publishedAt", - type: "date", + name: 'publishedAt', + type: 'date', admin: { - position: "sidebar", + position: 'sidebar', date: { - pickerAppearance: "dayAndTime", + pickerAppearance: 'dayAndTime', }, }, hooks: { beforeChange: [ ({ siblingData, value }) => { - if (siblingData._status === "published" && !value) { - return new Date(); + if (siblingData._status === 'published' && !value) { + return new Date() } - return value; + return value }, ], }, }, slugField(), ], -}; +} diff --git a/src/payload/payload.config.ts b/src/payload/payload.config.ts index 5e0de2a..46a5ece 100644 --- a/src/payload/payload.config.ts +++ b/src/payload/payload.config.ts @@ -1,5 +1,6 @@ import { webpackBundler } from '@payloadcms/bundler-webpack' import { mongooseAdapter } from '@payloadcms/db-mongodb' +import { InlineCodeTextFeature, lexicalEditor, TreeViewFeature } from '@payloadcms/richtext-lexical' import { slateEditor } from '@payloadcms/richtext-slate' import dotenv from 'dotenv' import path from 'path' @@ -20,7 +21,6 @@ import BeforeLogin from './components/BeforeLogin' import { Footer } from './globals/Footer' import { Header } from './globals/Header' import { Settings } from './globals/Settings' -import { InlineCodeTextFeature, lexicalEditor, TreeViewFeature } from "@payloadcms/richtext-lexical"; dotenv.config({ path: path.resolve(__dirname, '../../.env'), @@ -54,9 +54,7 @@ export default buildConfig({ }), }, editor: lexicalEditor({ - features: ({defaultFeatures}) => [ - ...defaultFeatures, - ] + features: ({ defaultFeatures }) => [...defaultFeatures], }), db: mongooseAdapter({ url: process.env.DATABASE_URI, diff --git a/src/server.ts b/src/server.ts index c199303..0097488 100644 --- a/src/server.ts +++ b/src/server.ts @@ -5,7 +5,6 @@ import nextBuild from 'next/dist/build' import path from 'path' import payload from 'payload' - dotenv.config({ path: path.resolve(__dirname, '../.env'), })