diff --git a/.bundlewatch.config.json b/.bundlewatch.config.json
index ff6b8646ca9..60746474cce 100644
--- a/.bundlewatch.config.json
+++ b/.bundlewatch.config.json
@@ -6,7 +6,7 @@
},
{
"path": "./dist/assets/owid.mjs",
- "maxSize": "545 KB"
+ "maxSize": "565 KB"
}
],
"defaultCompression": "none"
diff --git a/adminSiteClient/GdocsIndexPage.tsx b/adminSiteClient/GdocsIndexPage.tsx
index 66e63e3d975..5f07d535007 100644
--- a/adminSiteClient/GdocsIndexPage.tsx
+++ b/adminSiteClient/GdocsIndexPage.tsx
@@ -33,6 +33,7 @@ const iconGdocTypeMap = {
[OwidGdocType.Fragment]: ,
[OwidGdocType.Article]: ,
[OwidGdocType.TopicPage]: ,
+ [OwidGdocType.LinearTopicPage]: ,
}
@observer
@@ -49,6 +50,7 @@ class GdocsIndexPageSearch extends React.Component<{
OwidGdocType.Fragment,
OwidGdocType.Article,
OwidGdocType.TopicPage,
+ OwidGdocType.LinearTopicPage,
]
return (
@@ -105,6 +107,7 @@ export class GdocsIndexPage extends React.Component
{
[OwidGdocType.Fragment]: false,
[OwidGdocType.Article]: false,
[OwidGdocType.TopicPage]: false,
+ [OwidGdocType.LinearTopicPage]: false,
}
@observable search = { value: "" }
diff --git a/baker/algolia/indexToAlgolia.tsx b/baker/algolia/indexToAlgolia.tsx
index 472117ba0a4..b311a7c4350 100644
--- a/baker/algolia/indexToAlgolia.tsx
+++ b/baker/algolia/indexToAlgolia.tsx
@@ -138,6 +138,8 @@ function generateGdocRecords(
switch (gdoc.content.type) {
case OwidGdocType.TopicPage:
return { type: "topic", importance: 3 }
+ case OwidGdocType.LinearTopicPage:
+ return { type: "topic", importance: 3 }
case OwidGdocType.Fragment:
// this should not happen because we filter out fragments; but we want to have an exhaustive switch/case so we include it
return { type: "other", importance: 0 }
diff --git a/db/migrateWpPostsToArchieMl.ts b/db/migrateWpPostsToArchieMl.ts
index 0697c05a9ae..2c7283edbe5 100644
--- a/db/migrateWpPostsToArchieMl.ts
+++ b/db/migrateWpPostsToArchieMl.ts
@@ -92,11 +92,12 @@ const migrate = async (): Promise => {
"created_at_in_wordpress",
"updated_at",
"featured_image"
- ).from(db.knexTable(Post.postsTable)) //.where("id", "=", "29766"))
+ ).from(db.knexTable(Post.postsTable)) // .where("id", "=", "58149"))
for (const post of posts) {
try {
const isEntry = entries.has(post.slug)
+ console.log("isEntry", isEntry)
const text = post.content
let relatedCharts: RelatedChart[] = []
if (isEntry) {
@@ -125,7 +126,8 @@ const migrate = async (): Promise => {
// Heading levels used to start at 2, in the new layout system they start at 1
// This function iterates all blocks recursively and adjusts the heading levels inline
- adjustHeadingLevels(archieMlBodyElements)
+ // If the article is an entry, we also put an
above and below h1's
+ adjustHeadingLevels(archieMlBodyElements, isEntry)
if (relatedCharts.length) {
const indexOfFirstHeading = archieMlBodyElements.findIndex(
@@ -189,7 +191,7 @@ const migrate = async (): Promise => {
// TODO: this discards block level elements - those might be needed?
refs: undefined,
type: isEntry
- ? OwidGdocType.TopicPage
+ ? OwidGdocType.LinearTopicPage
: OwidGdocType.Article,
// Provide an empty array to prevent the sticky nav from rendering at all
// Because if it isn't defined, it tries to automatically populate itself
diff --git a/db/model/Gdoc/htmlToEnriched.ts b/db/model/Gdoc/htmlToEnriched.ts
index 80a2ba4a502..93a30ca6621 100644
--- a/db/model/Gdoc/htmlToEnriched.ts
+++ b/db/model/Gdoc/htmlToEnriched.ts
@@ -34,6 +34,7 @@ import {
EnrichedBlockGraySection,
EnrichedBlockStickyRightContainer,
EnrichedBlockBlockquote,
+ EnrichedBlockHorizontalRule,
} from "@ourworldindata/utils"
import { match, P } from "ts-pattern"
import {
@@ -393,13 +394,28 @@ export function convertAllWpComponentsToArchieMLBlocks(
})
}
-export function adjustHeadingLevels(blocks: OwidEnrichedGdocBlock[]): void {
- for (const block of blocks) {
+export function adjustHeadingLevels(
+ blocks: OwidEnrichedGdocBlock[],
+ isEntry: boolean
+): void {
+ for (let i = 0; i < blocks.length; i++) {
+ const block = blocks[i]
if (block.type === "heading") {
- block.level = Math.max(block.level - 1, 1)
- }
- if ("children" in block) {
- adjustHeadingLevels(block.children as OwidEnrichedGdocBlock[])
+ if (isEntry && block.level === 1) {
+ const hr: EnrichedBlockHorizontalRule = {
+ type: "horizontal-rule",
+ parseErrors: [],
+ }
+ blocks.splice(i, 0, { ...hr })
+ blocks.splice(i + 2, 0, { ...hr })
+ i += 2
+ }
+ block.level = Math.max(1, block.level - 1)
+ } else if ("children" in block) {
+ adjustHeadingLevels(
+ block.children as OwidEnrichedGdocBlock[],
+ isEntry
+ )
}
}
}
@@ -848,23 +864,7 @@ function cheerioToArchieML(
.with({ tagName: "details" }, unwrapElementWithContext)
.with({ tagName: "div" }, (div) => {
const className = div.attribs.class || ""
- // Special handling for a div that we use to mark the "First published on..." notice
- if (className.includes("blog-info")) {
- const children = unwrapElementWithContext(div)
- const textChildren = children.content.filter(
- (c) => "type" in c && c.type === "text"
- ) as EnrichedBlockText[]
- const callout: EnrichedBlockCallout = {
- type: "callout",
- title: "",
- text: textChildren,
- parseErrors: [],
- }
- return {
- errors: [],
- content: [callout],
- }
- } else if (className.includes("pcrm")) {
+ if (className.includes("pcrm")) {
// pcrm stands for "preliminary collection of relevant material" which was used to designate entries
// that weren't fully polished, but then became a way to create a general-purpose "warning box".
const unwrapped = unwrapElementWithContext(element)
diff --git a/packages/@ourworldindata/utils/src/owidTypes.ts b/packages/@ourworldindata/utils/src/owidTypes.ts
index dd2126264e8..71820c23f4b 100644
--- a/packages/@ourworldindata/utils/src/owidTypes.ts
+++ b/packages/@ourworldindata/utils/src/owidTypes.ts
@@ -1343,6 +1343,7 @@ export enum OwidGdocType {
Article = "article",
TopicPage = "topic-page",
Fragment = "fragment",
+ LinearTopicPage = "linear-topic-page",
}
export interface OwidGdocInterface {
diff --git a/site/gdocs/OwidGdoc.tsx b/site/gdocs/OwidGdoc.tsx
index 8687373f8ad..dbdd7904bfc 100644
--- a/site/gdocs/OwidGdoc.tsx
+++ b/site/gdocs/OwidGdoc.tsx
@@ -44,6 +44,8 @@ type OwidGdocProps = OwidGdocInterface & {
const citationDescriptionsByArticleType: Record = {
[OwidGdocType.TopicPage]:
"Our articles and data visualizations rely on work from many different people and organizations. When citing this topic page, please also cite the underlying data sources. This topic page can be cited as:",
+ [OwidGdocType.LinearTopicPage]:
+ "Our articles and data visualizations rely on work from many different people and organizations. When citing this topic page, please also cite the underlying data sources. This topic page can be cited as:",
[OwidGdocType.Article]:
"Our articles and data visualizations rely on work from many different people and organizations. When citing this article, please also cite the underlying data sources. This article can be cited as:",
// This case should never occur as Fragments aren't baked and can't be viewed by themselves.
diff --git a/site/gdocs/OwidGdocHeader.tsx b/site/gdocs/OwidGdocHeader.tsx
index 2125f053e0d..7a49468770e 100644
--- a/site/gdocs/OwidGdocHeader.tsx
+++ b/site/gdocs/OwidGdocHeader.tsx
@@ -143,6 +143,36 @@ function OwidTopicPageHeader({
)
}
+function OwidLinearTopicPageHeader({
+ content,
+ authors,
+}: {
+ content: OwidGdocContent
+ authors: string[]
+}) {
+ return (
+
+ )
+}
+
export function OwidGdocHeader(props: {
content: OwidGdocContent
authors: string[]
@@ -153,6 +183,8 @@ export function OwidGdocHeader(props: {
return
if (props.content.type === OwidGdocType.TopicPage)
return
+ if (props.content.type === OwidGdocType.LinearTopicPage)
+ return
// Defaulting to ArticleHeader, but will require the value to be set for all docs going forward
return
}
diff --git a/site/gdocs/topic-page.scss b/site/gdocs/topic-page.scss
index 4e5ffa41d05..3068b60e837 100644
--- a/site/gdocs/topic-page.scss
+++ b/site/gdocs/topic-page.scss
@@ -2,6 +2,7 @@
* Topic Page
**/
+// These styles are used both for topic page and linear topic page headers
.topic-page-header {
background-color: $blue-10;
color: $blue-90;
@@ -22,10 +23,17 @@
p.topic-page-header__byline,
.topic-page-header__byline a {
color: $blue-60;
+ margin-bottom: 0;
+ @include sm-only {
+ font-size: 0.875rem;
+ }
+ }
+
+ // Applies to either .topic-page-header__byline or .topic-page-header__dateline, if specified
+ p:last-child {
margin-bottom: 34px;
@include sm-only {
margin-bottom: 16px;
- font-size: 0.875rem;
}
}
@@ -213,3 +221,51 @@
.centered-article-container--topic-page #article-citation h3 {
text-align: left;
}
+
+// Linear topic page customizations
+.centered-article-container--linear-topic-page {
+ .article-block__horizontal-rule
+ + h1.article-block__heading.h1-semibold
+ + .article-block__horizontal-rule {
+ // h1's have a bottom margin of 24px, which stacked atop the hr's 48px, is too large.
+ // this shrinks the second hr's margin-top so that it's 48px total, without affecting the
+ // margins of any h1 that might come directly after it.
+ margin-top: 24px;
+ }
+ h1.article-block__heading.h1-semibold {
+ font-size: 2.25rem;
+ a.deep-link {
+ margin-top: 19px;
+ }
+ @include sm-up {
+ font-size: 2.625rem;
+ a.deep-link {
+ margin-top: 23px;
+ }
+ }
+ }
+ h2.article-block__heading.h2-bold {
+ font-size: 1.5rem;
+ a.deep-link {
+ margin-top: 13px;
+ }
+ @include sm-up {
+ font-size: 2rem;
+ a.deep-link {
+ margin-top: 19px;
+ }
+ }
+ }
+ h3.article-block__heading.h3-bold {
+ font-size: 1.25rem;
+ a.deep-link {
+ margin-top: 10px;
+ }
+ @include sm-up {
+ font-size: 1.5rem;
+ a.deep-link {
+ margin-top: 12px;
+ }
+ }
+ }
+}