diff --git a/packages/@ourworldindata/grapher/src/sourcesTab/SourcesTab.tsx b/packages/@ourworldindata/grapher/src/sourcesTab/SourcesTab.tsx
index 43c4276ca03..812c4791130 100644
--- a/packages/@ourworldindata/grapher/src/sourcesTab/SourcesTab.tsx
+++ b/packages/@ourworldindata/grapher/src/sourcesTab/SourcesTab.tsx
@@ -2,7 +2,6 @@ import {
Bounds,
DEFAULT_BOUNDS,
MarkdownTextWrap,
- linkify,
OwidOrigin,
uniq,
excludeNullish,
@@ -14,9 +13,6 @@ import { faPencilAlt } from "@fortawesome/free-solid-svg-icons"
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome/index.js"
import { CoreColumn, OwidColumnDef } from "@ourworldindata/core-table"
-const formatText = (s: string): string =>
- linkify(s).replace(/(?:\r\n|\r|\n)/g, "
")
-
export interface SourcesTabManager {
adminBaseUrl?: string
columnsWithSources: CoreColumn[]
@@ -110,11 +106,12 @@ export class SourcesTab extends React.Component<{
// metadata V2 shortDescription
Variable description |
- |
+
+
+ |
) : null}
{coverage ? (
@@ -162,35 +159,34 @@ export class SourcesTab extends React.Component<{
source.dataPublishedBy ? (
Data published by |
- |
+
+
+ |
) : null}
{source.dataPublisherSource ? (
Data publisher's source |
- |
+
+
+ |
) : null}
{source.link ? (
Link |
- |
+
+
+ |
) : null}
{retrievedDate ? (
@@ -202,12 +198,12 @@ export class SourcesTab extends React.Component<{
{source.additionalInfo && (
-
+
+
+
)}
)
diff --git a/packages/@ourworldindata/utils/src/GdocsUtils.ts b/packages/@ourworldindata/utils/src/GdocsUtils.ts
index 0848ec4a2ce..5f3e391e2c7 100644
--- a/packages/@ourworldindata/utils/src/GdocsUtils.ts
+++ b/packages/@ourworldindata/utils/src/GdocsUtils.ts
@@ -1,8 +1,14 @@
import { spansToUnformattedPlainText } from "./Util.js"
import { gdocUrlRegex } from "./GdocsConstants.js"
-import { OwidGdocLinkJSON, Span } from "./owidTypes.js"
+import { EnrichedBlockText, OwidGdocLinkJSON, Span } from "./owidTypes.js"
import { Url } from "./urls/Url.js"
import urlSlug from "url-slug"
+import {
+ EveryMarkdownNode,
+ MarkdownRoot,
+ mdParser,
+} from "./MarkdownTextWrap/parser.js"
+import { P, match } from "ts-pattern"
export function getLinkType(urlString: string): OwidGdocLinkJSON["linkType"] {
const url = Url.fromURL(urlString)
@@ -40,3 +46,149 @@ export function getUrlTarget(urlString: string): string {
export function convertHeadingTextToId(headingText: Span[]): string {
return urlSlug(spansToUnformattedPlainText(headingText))
}
+
+const convertMarkdownNodeToSpan = (node: EveryMarkdownNode): Span[] => {
+ return match(node)
+ .with(
+ {
+ type: "text",
+ },
+ (n) => [
+ {
+ spanType: "span-simple-text" as const,
+ text: n.value,
+ } as Span,
+ ]
+ )
+ .with(
+ {
+ type: "textSegments",
+ },
+ (n) => n.children.flatMap(convertMarkdownNodeToSpan) as Span[]
+ )
+ .with(
+ {
+ type: "newline",
+ },
+ () => [
+ {
+ spanType: "span-simple-text" as const,
+ text: "\n",
+ } as Span,
+ ]
+ )
+ .with(
+ {
+ type: "whitespace",
+ },
+ () => [
+ {
+ spanType: "span-simple-text" as const,
+ text: " ",
+ } as Span,
+ ]
+ )
+ .with(
+ {
+ type: "detailOnDemand",
+ },
+ (n) => [
+ {
+ spanType: "span-dod" as const,
+ id: n.term,
+ children: n.children.flatMap(convertMarkdownNodeToSpan),
+ } as Span,
+ ]
+ )
+ .with(
+ {
+ type: "markdownLink",
+ },
+ (n) => [
+ {
+ spanType: "span-link" as const,
+ url: n.href,
+ children: n.children.flatMap(convertMarkdownNodeToSpan),
+ } as Span,
+ ]
+ )
+ .with(
+ {
+ type: "plainUrl",
+ },
+ (n) => [
+ {
+ spanType: "span-link" as const,
+ url: n.href,
+ children: [
+ {
+ spanType: "span-simple-text" as const,
+ text: n.href,
+ },
+ ],
+ } as Span,
+ ]
+ )
+ .with(
+ {
+ type: "bold",
+ },
+ (n) => [
+ {
+ spanType: "span-bold" as const,
+ children: n.children.flatMap(convertMarkdownNodeToSpan),
+ } as Span,
+ ]
+ )
+ .with(
+ {
+ type: P.union("italic", "plainItalic", "italicWithoutBold"),
+ },
+ (n) => [
+ {
+ spanType: "span-italic" as const,
+ children: n.children.flatMap(convertMarkdownNodeToSpan),
+ } as Span,
+ ]
+ )
+ .with(
+ {
+ type: P.union("bold", "plainBold", "boldWithoutItalic"),
+ },
+ (n) => [
+ {
+ spanType: "span-bold" as const,
+ children: n.children.flatMap(convertMarkdownNodeToSpan),
+ } as Span,
+ ]
+ )
+ .exhaustive()
+ //.otherwise(() => ({ spanType: "span-simple-text" as const, text: "" }))
+}
+
+const convertMarkdownNodesToSpans = (nodes: MarkdownRoot): Span[] =>
+ nodes.children.flatMap(convertMarkdownNodeToSpan)
+
+export const markdownToEnrichedTextBlock = (
+ markdown: string
+): EnrichedBlockText => {
+ const parsedMarkdown = mdParser.markdown.parse(markdown)
+ if (parsedMarkdown.status) {
+ const spans = convertMarkdownNodesToSpans(parsedMarkdown.value)
+ return {
+ type: "text",
+ value: spans,
+ parseErrors: [],
+ }
+ } else
+ return {
+ type: "text",
+ value: [],
+ parseErrors: [
+ {
+ message: `Failed to parse markdown - expected ${parsedMarkdown.expected} at ${parsedMarkdown.index}`,
+ isWarning: false,
+ },
+ ],
+ }
+}
diff --git a/packages/@ourworldindata/utils/src/index.ts b/packages/@ourworldindata/utils/src/index.ts
index 71d7dc2a93b..2111fbd5bf0 100644
--- a/packages/@ourworldindata/utils/src/index.ts
+++ b/packages/@ourworldindata/utils/src/index.ts
@@ -608,6 +608,7 @@ export {
getUrlTarget,
checkIsInternalLink,
convertHeadingTextToId,
+ markdownToEnrichedTextBlock,
} from "./GdocsUtils.js"
export {
diff --git a/site/DataPageV2Content.tsx b/site/DataPageV2Content.tsx
index c0d0719f23b..982e4b0cf96 100644
--- a/site/DataPageV2Content.tsx
+++ b/site/DataPageV2Content.tsx
@@ -10,13 +10,9 @@ import { ArticleBlocks } from "./gdocs/ArticleBlocks.js"
import { RelatedCharts } from "./blocks/RelatedCharts.js"
import {
DataPageV2ContentFields,
- mdParser,
- MarkdownRoot,
- EveryMarkdownNode,
- Span,
- EnrichedBlockText,
excludeNullish,
slugify,
+ markdownToEnrichedTextBlock,
} from "@ourworldindata/utils"
import { AttachmentsContext, DocumentContext } from "./gdocs/OwidGdoc.js"
import StickyNav from "./blocks/StickyNav.js"
@@ -24,158 +20,12 @@ import cx from "classnames"
import { DebugProvider } from "./gdocs/DebugContext.js"
import { CodeSnippet } from "./blocks/CodeSnippet.js"
import dayjs from "dayjs"
-import { P, match } from "ts-pattern"
declare global {
interface Window {
_OWID_DATAPAGEV2_PROPS: DataPageV2ContentFields
_OWID_GRAPHER_CONFIG: GrapherInterface
}
}
-
-const convertMarkdownNodeToSpan = (node: EveryMarkdownNode): Span[] => {
- return match(node)
- .with(
- {
- type: "text",
- },
- (n) => [
- {
- spanType: "span-simple-text" as const,
- text: n.value,
- } as Span,
- ]
- )
- .with(
- {
- type: "textSegments",
- },
- (n) => n.children.flatMap(convertMarkdownNodeToSpan) as Span[]
- )
- .with(
- {
- type: "newline",
- },
- () => [
- {
- spanType: "span-simple-text" as const,
- text: "\n",
- } as Span,
- ]
- )
- .with(
- {
- type: "whitespace",
- },
- () => [
- {
- spanType: "span-simple-text" as const,
- text: " ",
- } as Span,
- ]
- )
- .with(
- {
- type: "detailOnDemand",
- },
- (n) => [
- {
- spanType: "span-dod" as const,
- id: n.term,
- children: n.children.flatMap(convertMarkdownNodeToSpan),
- } as Span,
- ]
- )
- .with(
- {
- type: "markdownLink",
- },
- (n) => [
- {
- spanType: "span-link" as const,
- url: n.href,
- children: n.children.flatMap(convertMarkdownNodeToSpan),
- } as Span,
- ]
- )
- .with(
- {
- type: "plainUrl",
- },
- (n) => [
- {
- spanType: "span-link" as const,
- url: n.href,
- children: [
- {
- spanType: "span-simple-text" as const,
- text: n.href,
- },
- ],
- } as Span,
- ]
- )
- .with(
- {
- type: "bold",
- },
- (n) => [
- {
- spanType: "span-bold" as const,
- children: n.children.flatMap(convertMarkdownNodeToSpan),
- } as Span,
- ]
- )
- .with(
- {
- type: P.union("italic", "plainItalic", "italicWithoutBold"),
- },
- (n) => [
- {
- spanType: "span-italic" as const,
- children: n.children.flatMap(convertMarkdownNodeToSpan),
- } as Span,
- ]
- )
- .with(
- {
- type: P.union("bold", "plainBold", "boldWithoutItalic"),
- },
- (n) => [
- {
- spanType: "span-bold" as const,
- children: n.children.flatMap(convertMarkdownNodeToSpan),
- } as Span,
- ]
- )
- .exhaustive()
- //.otherwise(() => ({ spanType: "span-simple-text" as const, text: "" }))
-}
-
-const convertMarkdownNodesToSpans = (nodes: MarkdownRoot) =>
- nodes.children.flatMap(convertMarkdownNodeToSpan)
-
-const markdownToEnrichedTextBlock = (markdown: string): EnrichedBlockText => {
- const parsedMarkdown = mdParser.markdown.parse(markdown)
- if (parsedMarkdown.status) {
- const spans = convertMarkdownNodesToSpans(parsedMarkdown.value)
- return {
- type: "text",
- value: spans,
- parseErrors: [],
- }
- } else
- return {
- type: "text",
- value: [],
- parseErrors: [
- {
- message: `Failed to parse markdown - expected ${parsedMarkdown.expected} at ${parsedMarkdown.index}`,
- isWarning: false,
- },
- ],
- }
-}
-
export const OWID_DATAPAGE_CONTENT_ROOT_ID = "owid-datapageJson-root"
export const DataPageV2Content = ({