Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions add-imports.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import fs from 'fs';

function prependToFile(filePath, text) {
let content = fs.readFileSync(filePath, 'utf8');
if (!content.includes(text)) {
fs.writeFileSync(filePath, text + "\n" + content, 'utf8');
}
}

prependToFile('app/(frontend)/staff/[slug]/page.tsx', "import { extractTextFromLexical } from '@/utils/formatArticle';");
prependToFile('components/Article/ArticleRecommendations.tsx', "import { extractTextFromLexical } from '@/utils/formatArticle';");
prependToFile('components/Article/Photofeature/ArticleHeader.tsx', "import { renderLexicalHeadline } from '@/utils/formatArticle';");
prependToFile('components/Dashboard/Todos/TodoRow.tsx', "import { renderLexicalHeadline } from '@/utils/formatArticle';");
prependToFile('components/Opinion/OpinionSectionPage.tsx', "import { extractTextFromLexical } from '@/utils/formatArticle';");
prependToFile('scripts/seed-features.ts', "import { extractTextFromLexical } from '../utils/formatArticle';");
prependToFile('scripts/update-features-images.ts', "import { extractTextFromLexical } from '../utils/formatArticle';");

console.log("Imports added");
15 changes: 8 additions & 7 deletions app/(frontend)/[section]/[year]/[month]/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { cache } from 'react';
import { notFound } from 'next/navigation';
import { extractTextFromLexical } from '@/utils/formatArticle';
import { headers } from 'next/headers';
import { getPayload } from 'payload';
import config from '@/payload.config';
Expand Down Expand Up @@ -182,21 +183,21 @@ export async function generateMetadata({ params }: Args): Promise<Metadata> {
const sectionName = section.charAt(0).toUpperCase() + section.slice(1);
const seo = await getSeo();
const description = article.subdeck || fillSeoTemplate(seo.templates.articleFallbackDescription, {
title: article.title,
title: extractTextFromLexical(article.title),
section,
sectionTitle: sectionName,
siteName: seo.siteIdentity.siteName,
});

return {
title: `${sectionName} | ${article.title}`,
title: `${sectionName} | ${extractTextFromLexical(article.title)}`,
description,
authors: authors.map((name) => ({ name })),
alternates: {
canonical: canonicalPath,
},
openGraph: {
title: article.title,
title: typeof article.title === 'object' ? extractTextFromLexical(article.title) : article.title,
description,
type: 'article',
url: canonicalPath,
Expand All @@ -210,7 +211,7 @@ export async function generateMetadata({ params }: Args): Promise<Metadata> {
},
twitter: {
card: imageUrl ? 'summary_large_image' : 'summary',
title: article.title,
title: extractTextFromLexical(article.title),
description,
...(imageUrl && { images: [imageUrl] }),
},
Expand Down Expand Up @@ -275,7 +276,7 @@ export default async function ArticlePage({ params }: Args) {
const jsonLd = {
'@context': 'https://schema.org',
'@type': 'NewsArticle',
headline: article.title,
headline: extractTextFromLexical(article.title),
...(article.subdeck && { description: article.subdeck }),
...(image?.url && {
image: [image.url],
Expand Down Expand Up @@ -321,11 +322,11 @@ export default async function ArticlePage({ params }: Args) {
publishedDate={article.publishedDate || article.createdAt}
section={article.section}
slug={article.slug}
title={article.title}
title={extractTextFromLexical(article.title)}
wordCount={wordCount}
isStaff={isStaff}
/>
<ArticleScrollBar title={article.title} section={article.section} />
<ArticleScrollBar title={extractTextFromLexical(article.title)} section={article.section} />
<LayoutComponent article={article as unknown as Article} content={cleanContent} />
{canEdit && <InlineEditor articleId={article.id} />}
</>
Expand Down
3 changes: 2 additions & 1 deletion app/(frontend)/sitemap-news.xml/route.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { extractTextFromLexical } from '@/utils/formatArticle';
import { getPayload } from 'payload';
import config from '@/payload.config';
import { getSeo } from '@/lib/getSeo';
Expand Down Expand Up @@ -36,7 +37,7 @@ export async function GET() {
.map((doc) => {
const url = `${siteUrl}${getArticleUrl(doc)}`;
const pubDate = new Date(doc.publishedDate || doc.createdAt).toISOString();
const title = doc.title.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
const title = (typeof doc.title === 'string' ? doc.title : extractTextFromLexical(doc.title)).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
return ` <url>
<loc>${url}</loc>
<news:news>
Expand Down
3 changes: 2 additions & 1 deletion app/(frontend)/staff/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { extractTextFromLexical } from '@/utils/formatArticle';
import React, { cache } from 'react';
import type { Metadata } from 'next';
import { getPayload } from 'payload';
Expand Down Expand Up @@ -61,7 +62,7 @@ const toPublicStaffUser = (user: PublicStaffUserSource): StaffProfileUser => ({

const toPublicStaffArticle = (article: PublicStaffArticleSource): StaffProfileArticle => ({
id: article.id,
title: article.title,
title: extractTextFromLexical(article.title),
slug: article.slug,
section: article.section,
publishedDate: article.publishedDate,
Expand Down
2 changes: 1 addition & 1 deletion app/api/search/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
return [...forms].filter(f => f.trim().length > 0);
}

type PayloadSearchArticle = {

Check warning on line 31 in app/api/search/route.ts

View workflow job for this annotation

GitHub Actions / validate

'PayloadSearchArticle' is defined but never used
id: number;
title: string;
slug?: string | null;
Expand Down Expand Up @@ -83,7 +83,7 @@
});

const articles = result.docs
.map((doc) => formatArticle(doc as PayloadSearchArticle, { absoluteDate: true }))
.map((doc) => formatArticle(doc as unknown as Parameters<typeof formatArticle>[0], { absoluteDate: true }))
.filter((a): a is Article => a !== null);

return {
Expand Down
3 changes: 2 additions & 1 deletion app/api/search/spellcheck/route.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { NextRequest } from "next/server";
import { extractTextFromLexical } from '@/utils/formatArticle';
import { getPayload } from "payload";
import config from "@/payload.config";
import { Pool } from "pg";
Expand Down Expand Up @@ -82,7 +83,7 @@ async function getCorpus(): Promise<Map<string, number>> {
},
});
for (const doc of docs) {
for (const w of extractWords(doc.title)) {
for (const w of extractWords(typeof doc.title === 'string' ? doc.title : extractTextFromLexical(doc.title))) {
corpus.set(w, (corpus.get(w) || 0) + 1);
}
}
Expand Down
44 changes: 41 additions & 3 deletions collections/Articles.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { CollectionConfig } from 'payload'
import { lexicalEditor, BoldFeature, ItalicFeature } from '@payloadcms/richtext-lexical'
import { getPostHogClient } from '../lib/posthog-server'

const Articles: CollectionConfig = {
Expand Down Expand Up @@ -48,12 +49,26 @@

if (isNowPublished && !wasPublished) {
const posthog = getPostHogClient()

let plainTitle = '';
if (doc.title && typeof doc.title === 'object' && doc.title.root) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const extractText = (node: any): string => {
if (node.type === 'text') return node.text || '';
if (node.children) return node.children.map(extractText).join('');
return '';
};
plainTitle = extractText(doc.title.root);
} else if (typeof doc.title === 'string') {
plainTitle = doc.title;
}

posthog?.capture({
distinctId: String(req.user?.id || 'unknown'),
event: 'article_published',
properties: {
article_id: doc.id,
article_title: doc.title,
article_title: plainTitle,
article_section: doc.section,
article_slug: doc.slug,
},
Expand Down Expand Up @@ -93,7 +108,20 @@
}

// Auto-generate slug from title if not set, or sanitize existing slug
const rawSlug = data.slug || data.title || ''
let plainTitle = '';
if (data.title && typeof data.title === 'object' && data.title.root) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const extractText = (node: any): string => {
if (node.type === 'text') return node.text || '';
if (node.children) return node.children.map(extractText).join('');
return '';
};
plainTitle = extractText(data.title.root);
} else if (typeof data.title === 'string') {
plainTitle = data.title;
}

const rawSlug = data.slug || plainTitle || ''
if (rawSlug) {
data.slug = rawSlug
.toLowerCase()
Expand All @@ -120,7 +148,17 @@
],
required: true,
},
{ name: 'title', type: 'text', required: true },
{
name: 'title',
type: 'richText',
required: true,
editor: lexicalEditor({
features: ({ defaultFeatures }) => [

Check warning on line 156 in collections/Articles.ts

View workflow job for this annotation

GitHub Actions / validate

'defaultFeatures' is defined but never used
BoldFeature(),
ItalicFeature(),
],
}),
},
{
name: 'kicker',
type: 'text',
Expand Down
2 changes: 1 addition & 1 deletion components/Archive/ArchiveTimeMachinePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ function ArchiveArticleRow({ article }: { article: Article }) {
article.section === "opinion" ? "font-light" : "font-bold"
} ${article.section === "sports" ? "font-normal tracking-[0.015em]" : ""} ${article.section === "features" ? "font-light" : ""}`}
>
{article.title}
{article.richTitle || article.title}
</h2>
<Byline author={article.author} date={article.date} className="mt-2 block" />
{article.excerpt && (
Expand Down
3 changes: 2 additions & 1 deletion components/Article/ArticleHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import Image from 'next/image';
import Link from 'next/link';
import { Article, Media, User } from '@/payload-types';
import { renderLexicalHeadline } from '@/utils/formatArticle';
import { ArticleByline } from './ArticleByline';

type Props = {
Expand All @@ -24,7 +25,7 @@ export const ArticleHeader: React.FC<Props> = ({ article }) => {
</span>
)}
<h1 data-ie-field="title" className={`font-bold text-[39px] md:text-[34px] lg:text-[42px] text-text-main leading-[1.05] tracking-[-0.02em] transition-colors font-copy ${article.section === "opinion" ? "font-light" : ""} ${article.section === "sports" ? "font-normal tracking-[0.015em]" : ""} ${article.section === "features" ? "font-light" : ""}`}>
{article.title}
{renderLexicalHeadline(article.title)}
</h1>
{article.subdeck && (
<h2 data-ie-field="subdeck" className="font-meta text-xl md:text-2xl font-normal text-text-muted leading-snug transition-colors">
Expand Down
3 changes: 2 additions & 1 deletion components/Article/ArticleRecommendations.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { extractTextFromLexical } from '@/utils/formatArticle';
import React from 'react';
import Image from 'next/image';
import { getPayload } from 'payload';
Expand Down Expand Up @@ -148,7 +149,7 @@ const toPublicRecommendationAuthor = (author: User): RecommendationAuthor => ({

const toPublicRecommendationArticle = (article: Article): RecommendationArticle => ({
id: article.id,
title: article.title,
title: extractTextFromLexical(article.title),
slug: article.slug,
subdeck: article.subdeck,
section: article.section,
Expand Down
3 changes: 2 additions & 1 deletion components/Article/Photofeature/ArticleHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
'use client';
import { renderLexicalHeadline } from '@/utils/formatArticle';

import React, { useState } from 'react';
import Image from 'next/image';
Expand Down Expand Up @@ -102,7 +103,7 @@ export const ArticleHeader: React.FC<Props> = ({ article }) => {
<div className="max-w-[90vw] w-full space-y-1">

<h1 data-ie-field="title" className={`font-copy font-bold text-[43px] md:text-[38px] lg:text-[47px] text-white leading-[1.05] tracking-[-0.02em] drop-shadow-lg ${article.section === "opinion" ? "font-light" : ""} ${article.section === "sports" ? "font-normal tracking-[0.015em]" : ""} ${article.section === "features" ? "font-light" : ""} pointer-events-auto`}>
{article.title}
{renderLexicalHeadline(article.title)}
</h1>

{/* Author and Date */}
Expand Down
3 changes: 2 additions & 1 deletion components/Dashboard/Todos/TodoRow.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { renderLexicalHeadline } from '@/utils/formatArticle';
import React from 'react'
import Link from 'next/link'
import type { Article, User } from '@/payload-types.ts'
Expand All @@ -20,7 +21,7 @@ export const TodoRow = ({ article }: { article: Article }) => {
className={`todo-row ${isPublished ? 'published' : 'draft'}`}
>
<div className="todo-col-main">
<span className="todo-title">{article.title || 'Untitled'}</span>
<span className="todo-title">{renderLexicalHeadline(article.title) || 'Untitled'}</span>
<span className="todo-meta">
{article.section} • {article.authors?.map((a) => (a as User).firstName).join(', ')}
</span>
Expand Down
2 changes: 1 addition & 1 deletion components/Features/FeaturesListPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export default function FeaturesListPage({
)}
<div className="flex flex-col justify-center">
<h2 className="font-copy font-medium leading-[1.15] text-[22px] text-text-main transition-colors group-hover:text-accent">
{article.title}
{article.richTitle || article.title}
</h2>
<Byline author={article.author} date={article.date} className="text-[13px]" />
{article.excerpt && (
Expand Down
6 changes: 3 additions & 3 deletions components/Features/FeaturesSectionPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ function FeaturesCard({
className="font-copy font-medium leading-[1.12] text-text-main transition-colors group-hover:text-accent"
style={{ fontSize: large ? 34 : 20 }}
>
{article.title}
{article.richTitle || article.title}
</h3>
<Byline
author={article.author}
Expand Down Expand Up @@ -645,7 +645,7 @@ export default function FeaturesSectionPage({
className="font-copy font-medium leading-[1.12] text-text-main transition-colors group-hover:text-accent"
style={{ fontSize: 28 }}
>
{wideArticle[0].title}
{wideArticle[0].richTitle || wideArticle[0].title}
</h2>
<Byline author={wideArticle[0].author} date={wideArticle[0].date} variant="features" className="mt-2 text-[13px]" />
{wideArticle[0].excerpt && (
Expand Down Expand Up @@ -809,7 +809,7 @@ export default function FeaturesSectionPage({
</span>
)}
<h3 className="font-copy font-medium leading-[1.12] text-[28px] text-text-main transition-colors group-hover:text-accent">
{article.title}
{article.richTitle || article.title}
</h3>
<Byline author={article.author} variant="features" className="mt-2 text-[13px]" />
</TransitionLink>
Expand Down
2 changes: 1 addition & 1 deletion components/FrontPage/ArticleCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export const ArticleCard = ({
data-marauders-title
className={`relative z-[30] font-bold leading-[1.12] tracking-[-0.01em] text-text-main transition-colors [overflow-wrap:anywhere] break-words font-copy ${article.section === "opinion" ? "font-light" : ""} ${titleClassName} ${article.section === "news" ? "text-[23px] md:text-[25px]" : ""} ${article.section === "sports" ? "font-normal tracking-[0.015em]" : ""} ${article.section === "features" ? "font-light text-[23px] md:text-[25px]" : ""}`}
>
{article.title}
{article.richTitle || article.title}
</h3>
<Byline author={article.author} date={article.date} />
{showExcerpt && article.excerpt && (
Expand Down
2 changes: 1 addition & 1 deletion components/FrontPage/ArticleListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const ArticleListItem = ({ article }: { article: Article }) => (
<li className={`border-t border-rule py-3 first:border-t-0 first:pt-0${article.isFollytechnic ? ' follytechnic' : ''}`}>
<TransitionLink href={getArticleUrl(article)} className="group block" data-header-anchor="text">
<h4 className={`text-[22px] md:text-[24px] font-bold leading-[1.12] tracking-[-0.01em] text-text-main transition-colors font-copy ${article.section === "opinion" ? "font-light" : ""} ${article.section === "news" ? "text-[23px] md:text-[25px]" : ""} ${article.section === "sports" ? "font-normal tracking-[0.015em]" : ""} ${article.section === "features" ? "font-light text-[23px] md:text-[25px]" : ""}`}>
{article.title}
{article.richTitle || article.title}
</h4>
<Byline author={article.author} date={article.date} className="mt-1 block text-[10px] md:text-[10px]" />
</TransitionLink>
Expand Down
2 changes: 1 addition & 1 deletion components/FrontPage/CompactArticle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { getArticleUrl } from '@/utils/getArticleUrl';
export const CompactArticle = ({ article }: { article: Article }) => (
<Link href={getArticleUrl(article)} className={`flex flex-col group cursor-pointer h-full justify-start${article.isFollytechnic ? ' follytechnic' : ''}`}>
<h3 className={`font-copy font-bold text-text-main mb-1 text-[16px] md:text-[18px] leading-tight transition-colors ${article.section === "news" ? "!text-[1.2em]" : ""} ${article.section === "sports" ? "font-normal tracking-[0.015em]" : ""} ${article.section === "features" ? "font-light text-[17px] md:text-[19px]" : ""}`}>
{article.title}
{article.richTitle || article.title}
</h3>
<Byline author={article.author} date={article.date} />
<p className="font-meta text-text-main text-[13px] md:text-[14px] font-normal leading-[1.4] mb-2 transition-colors">
Expand Down
4 changes: 2 additions & 2 deletions components/FrontPage/GridLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ function GridArticleCard({
data-marauders-title
className={`relative z-[30] font-copy font-bold leading-[1.08] tracking-[-0.015em] text-text-main transition-colors [overflow-wrap:anywhere] break-words ${titleSize} ${article.section === "news" ? "!text-[1.2em]" : ""} ${article.section === "sports" ? "font-normal tracking-[0.015em]" : ""} ${article.section === "features" ? "font-light" : ""} ${article.section === "opinion" ? "font-light" : ""}`}
>
{article.title}
{article.richTitle || article.title}
</h3>
<Byline author={article.author} date={article.date} split={isLarge} />
{article.excerpt && (
Expand Down Expand Up @@ -170,7 +170,7 @@ function MobileArticleCard({ article }: { article: Article }) {
data-marauders-title
className={`relative z-[30] font-copy font-bold leading-[1.08] tracking-[-0.015em] text-text-main transition-colors [overflow-wrap:anywhere] break-words text-[26px] ${article.section === "news" ? "!text-[1.2em]" : ""} ${article.section === "sports" ? "font-normal tracking-[0.015em]" : ""} ${article.section === "features" ? "font-light" : ""} ${article.section === "opinion" ? "font-light" : ""}`}
>
{article.title}
{article.richTitle || article.title}
</h3>
<Byline author={article.author} date={article.date} />
{article.excerpt && (
Expand Down
Loading
Loading