Skip to content

Commit

Permalink
feat(show): use show description as meta description
Browse files Browse the repository at this point in the history
This patch updates the show page description to use the show description
if it exists, and revert back to the Vogue inspired description if it
does not.

This patch also adds some XSS support that may be somewhat premature,
but was easy enough to add that it felt it wouldn't hurt.

Closes: NC-666
  • Loading branch information
nicholaschiang committed Aug 19, 2023
1 parent b2c0f04 commit 02714c7
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { prisma } from 'db.server'
import { type Filter, FILTER_PARAM, filterToSearchParam } from 'filters'
import { log } from 'log.server'
import { type Handle } from 'root'
import { sanitize } from 'sanitize.server'
import { getUserId } from 'session.server'

import { About } from './about'
Expand All @@ -39,7 +40,9 @@ export const meta: V2_MetaFunction<typeof loader> = ({ data }) => {
{ title: `${data.brand.name} ${getShowSeason(data)} Collection | ${NAME}` },
{
name: 'description',
content: `${data.name} collection, runway looks, beauty, models, and reviews.`,
content: data.description
? sanitize(data.description, { allowedTags: [] })
: `${data.name} collection, runway looks, beauty, models, and reviews.`,
},
{ name: 'keywords', content: keywords },
{ name: 'news_keywords', content: keywords },
Expand Down Expand Up @@ -142,10 +145,26 @@ export async function loader({ request, params }: LoaderArgs) {
})
if (show == null) throw miss
log.debug('got show %o', show)

// Sanitize HTML (perhaps this should be in a separate helper function).
/* eslint-disable no-param-reassign */
show.articles.forEach((article) => {
article.content = sanitize(article.content)
})
show.description = sanitize(show.description)
show.collections.forEach((collection) => {
collection.designers.forEach((designer) => {
designer.description = sanitize(designer.description)
})
})
/* eslint-enable no-param-reassign */

// Derive the show's scores and get the current user's review of it.
const [scores, review] = await Promise.all([
getScores(show.id),
getReview(show.id, request),
])

return { ...show, scores, review }
}

Expand Down
8 changes: 8 additions & 0 deletions app/sanitize.server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import sanitizeHtml from 'sanitize-html'

export function sanitize(html: string, options?: sanitizeHtml.IOptions): string
export function sanitize(html: null, options?: sanitizeHtml.IOptions): null
export function sanitize(html: string | null, options?: sanitizeHtml.IOptions): string | null
export function sanitize(html: string | null, options?: sanitizeHtml.IOptions) {
return html ? sanitizeHtml(html, options) : html
}
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
"react-simple-maps": "^3.0.0",
"remix-sitemap": "^2.2.0",
"rfdc": "^1.3.0",
"sanitize-html": "^2.11.0",
"schema-dts": "^1.1.2",
"sharp": "^0.32.4",
"tailwind-merge": "^1.14.0",
Expand Down Expand Up @@ -131,6 +132,7 @@
"@types/react": "^18.2.20",
"@types/react-dom": "^18.2.7",
"@types/react-simple-maps": "^3.0.0",
"@types/sanitize-html": "^2.9.0",
"@types/sharp": "^0.31.1",
"@types/user-agents": "^1.0.2",
"@typescript-eslint/eslint-plugin": "^5.62.0",
Expand Down
36 changes: 27 additions & 9 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 18 additions & 1 deletion remix.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,24 @@ module.exports = {
cacheDirectory: './node_modules/.cache/remix',
ignoredRouteFiles: ['**/.*', '**/*.css', '**/*.test.{js,jsx,ts,tsx}'],
serverModuleFormat: 'cjs',
serverDependenciesToBundle: ['nanoid/non-secure', /d3-.*/],
serverDependenciesToBundle: [
// TODO figure out why I need to do this; why can't Vercel just include
// these in the `node_modules` and resolve them normally? I'm guessing this
// is because `sanitize-html` uses `require()` and not `import` (and thus it
// is not recognized by Vercel's Edge Runtime).
// @see {@link https://vercel.com/docs/functions/edge-functions/edge-runtime#unsupported-apis}
'sanitize-html',
'htmlparser2',
'escape-string-regexp',
'is-plain-object',
'deepmerge',
'parse-srcset',
'postcss',
// TODO why did I have to mark `nanoid` as a server dependency?
'nanoid/non-secure',
// TODO why can't the D3 packages be resolved normally?
/d3-.*/,
],
images: {
sizes: [200, 300, 400, 500, 600, 700, 800, 900, 1000],
domains: ['aritzia.scene7.com'],
Expand Down

0 comments on commit 02714c7

Please sign in to comment.