Skip to content

Commit

Permalink
Merge pull request #325 from executablebooks/agoose77/fix-frontmatter
Browse files Browse the repository at this point in the history
🏷 Pull frontmatter from proper key
  • Loading branch information
fwkoch authored Apr 19, 2024
2 parents ca7eb5c + 41d0171 commit 65a2bab
Show file tree
Hide file tree
Showing 14 changed files with 207 additions and 43 deletions.
5 changes: 5 additions & 0 deletions .changeset/modern-weeks-repeat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@myst-theme/book': patch
---

Migrated to V2 Remix meta function pattern
6 changes: 6 additions & 0 deletions .changeset/ninety-planes-pump.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@myst-theme/common': minor
'@myst-theme/site': minor
---

Migrated to meta helper functions to the Remix V2 pattern, old meta helpers functions are still available with a `_v1` suffix.
5 changes: 3 additions & 2 deletions packages/common/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ export function getProject(
projectSlug?: string,
): ManifestProject | undefined {
if (!config) return undefined;
if (!projectSlug) return config.projects?.[0];
const project = config.projects?.find((p) => p.slug === projectSlug);
if (!config.projects || config.projects.length === 0) return undefined;
if (!projectSlug) return config.projects[0];
const project = config.projects?.find((p) => p.slug === projectSlug) ?? config.projects[0];
return project;
}

Expand Down
66 changes: 63 additions & 3 deletions packages/site/src/seo/meta.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import type { HtmlMetaDescriptor } from '@remix-run/react';
import type { HtmlMetaDescriptor, V2_MetaDescriptor } from '@remix-run/react';

type SocialSite = {
title: string;
description?: string;
twitter?: string;
};

Expand All @@ -20,15 +21,38 @@ function allDefined(meta: Record<string, string | null | undefined>): HtmlMetaDe
return Object.fromEntries(Object.entries(meta).filter(([, v]) => v)) as HtmlMetaDescriptor;
}

export function getMetaTagsForSite({ title, twitter }: SocialSite): HtmlMetaDescriptor {
export function getMetaTagsForSite_V1({
title,
description,
twitter,
}: SocialSite): HtmlMetaDescriptor {
const meta = {
title,
description,
'twitter:site': twitter ? `@${twitter.replace('@', '')}` : undefined,
};
return allDefined(meta);
}

export function getMetaTagsForArticle({
export function getMetaTagsForSite({
title,
description,
twitter,
}: SocialSite): V2_MetaDescriptor[] {
const meta: V2_MetaDescriptor[] = [
{ title },
{ property: 'og:title', content: title },
{ name: 'generator', content: 'mystmd' },
];
if (description) {
meta.push({ name: 'description', content: description });
meta.push({ property: 'og:description', content: description });
}
if (twitter) meta.push({ name: 'twitter:site', content: `@${twitter.replace('@', '')}` });
return meta;
}

export function getMetaTagsForArticle_V1({
origin,
url,
title,
Expand All @@ -55,3 +79,39 @@ export function getMetaTagsForArticle({
};
return allDefined(meta);
}

export function getMetaTagsForArticle({
origin,
url,
title,
description,
image,
twitter,
keywords,
}: SocialArticle): V2_MetaDescriptor[] {
const meta: V2_MetaDescriptor[] = [
{ title },
{ property: 'og:title', content: title },
{ name: 'generator', content: 'mystmd' },
];
if (description) {
meta.push({ name: 'description', content: description });
meta.push({ property: 'og:description', content: description });
}
if (keywords) meta.push({ name: 'keywords', content: keywords.join(', ') });
if (origin && url) meta.push({ property: 'og:url', content: `${origin}${url}` });
if (image) {
meta.push({ name: 'image', content: image });
meta.push({ property: 'og:image', content: image });
}
if (twitter) {
meta.push({ name: 'twitter:card', content: image ? 'summary_large_image' : 'summary' });
meta.push({ name: 'twitter:creator', content: `@${twitter.replace('@', '')}` });
meta.push({ name: 'twitter:title', content: title });
if (description) meta.push({ name: 'twitter:description', content: description });
if (image) meta.push({ name: 'twitter:image', content: image });
meta.push({ name: 'twitter:alt', content: title });
}

return meta;
}
5 changes: 3 additions & 2 deletions themes/article/app/root.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { LinksFunction, MetaFunction, LoaderFunction } from '@remix-run/node';
import type { LinksFunction, MetaFunction, LoaderFunction, V2_MetaFunction } from '@remix-run/node';
import tailwind from '~/styles/app.css';
import thebeCoreCss from 'thebe-core/dist/lib/thebe-core.css';
import { getConfig } from '~/utils/loaders.server';
Expand All @@ -14,9 +14,10 @@ import {
import { Outlet, useLoaderData } from '@remix-run/react';
export { AppCatchBoundary as CatchBoundary } from '@myst-theme/site';

export const meta: MetaFunction = ({ data }) => {
export const meta: V2_MetaFunction = ({ data }) => {
return getMetaTagsForSite({
title: data?.config?.title,
description: data?.config?.description,
twitter: data?.config?.options?.twitter,
});
};
Expand Down
42 changes: 30 additions & 12 deletions themes/article/app/routes/$.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { isFlatSite, type PageLoader } from '@myst-theme/common';
import type { LinksFunction, LoaderFunction, MetaFunction } from '@remix-run/node';
import { getProject, isFlatSite, type PageLoader } from '@myst-theme/common';
import {
json,
type LinksFunction,
type LoaderFunction,
type V2_MetaFunction,
} from '@remix-run/node';
import { getMetaTagsForArticle, KatexCSS, ArticlePageCatchBoundary } from '@myst-theme/site';
import { getConfig, getPage } from '~/utils/loaders.server';
import { useLoaderData } from '@remix-run/react';
Expand All @@ -10,16 +15,28 @@ import { ComputeOptionsProvider } from '@myst-theme/jupyter';
import { ProjectProvider, useBaseurl } from '@myst-theme/providers';
import { ThebeLoaderAndServer } from '@myst-theme/jupyter';

export const meta: MetaFunction = (args) => {
const config = args.parentsData?.root?.config as SiteManifest | undefined;
const data = args.data as PageLoader | undefined;
if (!config || !data || !data.frontmatter) return {};
type ManifestProject = Required<SiteManifest>['projects'][0];

export const meta: V2_MetaFunction = ({ data, matches, location }) => {
if (!data) return [];

const config: SiteManifest = data.config;
const project: ManifestProject = data.project;
const page: PageLoader['frontmatter'] = data.page.frontmatter;

return getMetaTagsForArticle({
origin: '',
url: args.location.pathname,
title: `${data.frontmatter.title} - ${config?.title}`,
description: data.frontmatter.description,
image: (data.frontmatter.thumbnailOptimized || data.frontmatter.thumbnail) ?? undefined,
url: location.pathname,
title: page.title
? `${page.title} - ${config?.title ?? project.title}`
: `${config?.title ?? project.title}`,
description: page.description ?? project.description ?? config.description ?? undefined,
image:
(page.thumbnailOptimized || page.thumbnail) ??
(project.thumbnailOptimized || project.thumbnail) ??
undefined,
twitter: config?.options?.twitter,
keywords: page.keywords ?? project.keywords ?? config.keywords ?? [],
});
};

Expand All @@ -30,21 +47,22 @@ export const loader: LoaderFunction = async ({ params, request }) => {
const projectName = second ? first : undefined;
const slug = second || first;
const config = await getConfig();
const project = getProject(config, projectName ?? slug);
const flat = isFlatSite(config);
const page = await getPage(request, {
project: flat ? projectName : projectName ?? slug,
slug: flat ? slug : projectName ? slug : undefined,
redirect: process.env.MODE === 'static' ? false : true,
});
return page;
return json({ config, project, page });
};

export default function Page() {
// TODO handle outline?
// const { container, outline } = useOutlineHeight();
// const { hide_outline } = (article.frontmatter as any)?.options ?? {};
const baseurl = useBaseurl();
const article = useLoaderData<PageLoader>() as PageLoader;
const { page: article } = useLoaderData() as { page: PageLoader };

return (
<ArticlePageAndNavigation>
Expand Down
34 changes: 30 additions & 4 deletions themes/article/app/routes/_index.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,45 @@
import { ProjectPageCatchBoundary, responseNoArticle, responseNoSite } from '@myst-theme/site';
import {
ProjectPageCatchBoundary,
getMetaTagsForArticle,
responseNoArticle,
responseNoSite,
} from '@myst-theme/site';
import Page from './$';
import { ArticlePageAndNavigation } from '../components/ArticlePageAndNavigation';
import { getConfig, getPage } from '../utils/loaders.server';
import type { LoaderFunction } from '@remix-run/node';
import type { LoaderFunction, V2_MetaFunction } from '@remix-run/node';
import { redirect } from '@remix-run/node';
import { SiteManifest } from 'myst-config';
import { getProject } from '@myst-theme/common';
export { links } from './$';

type ManifestProject = Required<SiteManifest>['projects'][0];

export const meta: V2_MetaFunction = ({ data, location }) => {
if (!data) return [];

const config: SiteManifest = data.config;
const project: ManifestProject = data.project;

return getMetaTagsForArticle({
origin: '',
url: location.pathname,
title: config?.title ?? project.title,
description: config.description ?? project.description ?? undefined,
image: (project.thumbnailOptimized || project.thumbnail) ?? undefined,
keywords: config.keywords ?? project.keywords ?? [],
twitter: config?.options?.twitter,
});
};

export const loader: LoaderFunction = async ({ params, request }) => {
const config = await getConfig();
if (!config) throw responseNoSite();
const project = config?.projects?.[0];
const project = getProject(config);
if (!project) throw responseNoArticle();
if (project.slug) return redirect(`/${project.slug}`);
const page = await getPage(request, { slug: project.index });
return page;
return { config, project, page };
};

export default Page;
Expand Down
1 change: 1 addition & 0 deletions themes/article/remix.config.dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,6 @@ module.exports = {
v2_routeConvention: true,
v2_normalizeFormMethod: true,
v2_headers: true,
v2_meta: true,
},
};
1 change: 1 addition & 0 deletions themes/article/remix.config.prod.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ module.exports = {
v2_routeConvention: true,
v2_normalizeFormMethod: true,
v2_headers: true,
v2_meta: true,
},
};
5 changes: 3 additions & 2 deletions themes/book/app/root.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { LinksFunction, MetaFunction, LoaderFunction } from '@remix-run/node';
import type { LinksFunction, V2_MetaFunction, LoaderFunction } from '@remix-run/node';
import tailwind from '~/styles/app.css';
import thebeCoreCss from 'thebe-core/dist/lib/thebe-core.css';
import { getConfig } from '~/utils/loaders.server';
Expand All @@ -14,9 +14,10 @@ import {
import { Outlet, useLoaderData } from '@remix-run/react';
export { AppCatchBoundary as CatchBoundary } from '@myst-theme/site';

export const meta: MetaFunction = ({ data }) => {
export const meta: V2_MetaFunction = ({ data }) => {
return getMetaTagsForSite({
title: data?.config?.title,
description: data?.config?.description,
twitter: data?.config?.options?.twitter,
});
};
Expand Down
42 changes: 29 additions & 13 deletions themes/book/app/routes/$.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { json, type LinksFunction, type LoaderFunction, type MetaFunction } from '@remix-run/node';
import {
json,
type V2_MetaFunction,
type LinksFunction,
type LoaderFunction,
} from '@remix-run/node';
import { getProject, isFlatSite, type PageLoader } from '@myst-theme/common';
import {
getMetaTagsForArticle,
KatexCSS,
ArticlePage,
useOutlineHeight,
Expand All @@ -10,6 +14,7 @@ import {
Navigation,
TopNav,
ArticlePageCatchBoundary,
getMetaTagsForArticle,
} from '@myst-theme/site';
import { getConfig, getPage } from '~/utils/loaders.server';
import { useLoaderData } from '@remix-run/react';
Expand All @@ -25,16 +30,28 @@ import {
import { MadeWithMyst } from '@myst-theme/icons';
import { ComputeOptionsProvider, ThebeLoaderAndServer } from '@myst-theme/jupyter';

export const meta: MetaFunction = (args) => {
const config = args.parentsData?.root?.config as SiteManifest | undefined;
const data = args.data as PageLoader | undefined;
if (!config || !data || !data.frontmatter) return {};
type ManifestProject = Required<SiteManifest>['projects'][0];

export const meta: V2_MetaFunction = ({ data, matches, location }) => {
if (!data) return [];

const config: SiteManifest = data.config;
const project: ManifestProject = data.project;
const page: PageLoader['frontmatter'] = data.page.frontmatter;

return getMetaTagsForArticle({
origin: '',
url: args.location.pathname,
title: `${data.frontmatter.title} - ${config?.title}`,
description: data.frontmatter.description,
image: (data.frontmatter.thumbnailOptimized || data.frontmatter.thumbnail) ?? undefined,
url: location.pathname,
title: page.title
? `${page.title} - ${config?.title ?? project.title}`
: `${config?.title ?? project.title}`,
description: page.description ?? project.description ?? config.description ?? undefined,
image:
(page.thumbnailOptimized || page.thumbnail) ??
(project.thumbnailOptimized || project.thumbnail) ??
undefined,
twitter: config?.options?.twitter,
keywords: page.keywords ?? project.keywords ?? config.keywords ?? [],
});
};

Expand All @@ -52,11 +69,10 @@ export const loader: LoaderFunction = async ({ params, request }) => {
slug: flat ? slug : projectName ? slug : undefined,
redirect: process.env.MODE === 'static' ? false : true,
});
return json({ page, project });
console.log('isflat', flat, projectName, slug, page, project);
return json({ config, page, project });
};

type ManifestProject = Required<SiteManifest>['projects'][0];

export function ArticlePageAndNavigation({
children,
hide_toc,
Expand Down
Loading

0 comments on commit 65a2bab

Please sign in to comment.