Skip to content

Commit

Permalink
Merge pull request #2993 from owid/citation-tweaks
Browse files Browse the repository at this point in the history
🎉 Tweak citations, add them to the sources overlay
  • Loading branch information
danyx23 authored Dec 26, 2023
2 parents 72667ca + ddb4c03 commit f4ab296
Show file tree
Hide file tree
Showing 8 changed files with 218 additions and 93 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from "react"
import { CodeSnippet } from "../CodeSnippet/CodeSnippet.js"

export const DataCitation = (props: {
citationShort: string
citationLong: string
}) => {
return (
<>
{props.citationShort && (
<>
<p className="citation__paragraph">
<span className="citation__type">In-line citation</span>
<br />
If you have limited space (e.g. in data visualizations),
you can use this abbreviated in-line citation:
</p>
<CodeSnippet
code={props.citationShort}
theme="light"
useMarkdown={true}
/>
</>
)}
{props.citationLong && (
<>
<p className="citation__paragraph">
<span className="citation__type">Full citation</span>
</p>
<CodeSnippet
code={props.citationLong}
theme="light"
useMarkdown={true}
/>
</>
)}
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
margin: 0;
font-size: var(--content-size);

ol,
ul {
margin-left: 1em;

Expand All @@ -67,6 +68,26 @@
&:last-child {
margin-bottom: 0;
}
p {
margin: 0;
}
}
}

ol {
margin-left: 1em;

li {
margin: 0.5em 0; // half of the default margin for ordered lists, otherwise like unordered lists above
&:first-child {
margin-top: 0;
}
&:last-child {
margin-bottom: 0;
}
p {
margin: 0;
}
}
}

Expand All @@ -77,10 +98,6 @@
> *:last-child {
margin-bottom: 0;
}

ul li p {
margin: 0;
}
}

a {
Expand Down
2 changes: 2 additions & 0 deletions packages/@ourworldindata/components/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ export {
renderCodeSnippets,
} from "./CodeSnippet/CodeSnippet.js"

export { DataCitation } from "./DataCitation/DataCitation.js"

export {
DATAPAGE_ABOUT_THIS_DATA_SECTION_ID,
DATAPAGE_SOURCES_AND_PROCESSING_SECTION_ID,
Expand Down
8 changes: 8 additions & 0 deletions packages/@ourworldindata/grapher/src/modal/SourcesModal.scss
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,14 @@
margin-right: $tab-gap;
}

.citation__paragraph {
color: $light-text;
}

.citation__type {
color: $dark-text;
}

.indicator-processing .indicator-processing__link {
@include body-3-medium;
display: inline-block;
Expand Down
31 changes: 31 additions & 0 deletions packages/@ourworldindata/grapher/src/modal/SourcesModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@ import {
OwidSource,
IndicatorTitleWithFragments,
joinTitleFragments,
getCitationShort,
getCitationLong,
} from "@ourworldindata/utils"
import {
IndicatorSources,
IndicatorProcessing,
SimpleMarkdownText,
DataCitation,
} from "@ourworldindata/components"
import React from "react"
import { action, computed } from "mobx"
Expand Down Expand Up @@ -282,6 +285,27 @@ export class Source extends React.Component<{
return { ...this.column.def, source: this.column.source }
}

@computed get citationShort(): string {
return getCitationShort(
this.def.origins ?? [],
getAttributionFragmentsFromVariable(this.def),
this.def.owidProcessingLevel
)
}

@computed get citationLong(): string {
return getCitationLong(
this.title,
this.def.origins ?? [],
this.source,
getAttributionFragmentsFromVariable(this.def),
this.def.presentation?.attributionShort,
this.def.presentation?.titleVariant,
this.def.owidProcessingLevel,
undefined
)
}

@computed private get source(): OwidSource {
return this.def.source ?? {}
}
Expand Down Expand Up @@ -426,6 +450,13 @@ export class Source extends React.Component<{
<IndicatorProcessing
descriptionProcessing={this.def.descriptionProcessing}
/>
<h3 className="heading heading--tight">
How to cite this data:
</h3>
<DataCitation
citationShort={this.citationShort}
citationLong={this.citationLong}
/>
</div>
)
}
Expand Down
2 changes: 2 additions & 0 deletions packages/@ourworldindata/utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,8 @@ export {
splitSourceTextIntoFragments,
prepareSourcesForDisplay,
formatSourceDate,
getCitationLong,
getCitationShort,
} from "./metadataHelpers.js"

export {
Expand Down
83 changes: 82 additions & 1 deletion packages/@ourworldindata/utils/src/metadataHelpers.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { OwidOrigin } from "./OwidOrigin"
import { OwidProcessingLevel, OwidVariableWithSource } from "./OwidVariable"
import {
IndicatorTitleWithFragments,
OwidProcessingLevel,
OwidVariableWithSource,
} from "./OwidVariable"
import { DisplaySource } from "./owidTypes"
import { compact, uniq, last, excludeUndefined } from "./Util"
import dayjs from "./dayjs.js"
import { OwidSource } from "./OwidSource.js"

export function getOriginAttributionFragments(
origins: OwidOrigin[] | undefined
Expand Down Expand Up @@ -184,6 +189,82 @@ export const prepareSourcesForDisplay = (
return sourcesForDisplay
}

const getYearSuffixFromOrigin = (o: OwidOrigin): string => {
const year = o.dateAccessed
? dayjs(o.dateAccessed, ["YYYY-MM-DD", "YYYY"]).year()
: o.datePublished
? dayjs(o.datePublished, ["YYYY-MM-DD", "YYYY"]).year()
: undefined
if (year) return ` (${year})`
else return ""
}
export const getCitationShort = (
origins: OwidOrigin[],
attributions: string[],
owidProcessingLevel: OwidProcessingLevel | undefined
): string => {
const producersWithYear = uniq(
origins.map((o) => `${o.producer}${getYearSuffixFromOrigin(o)}`)
)
const processingLevelPhrase =
getPhraseForProcessingLevel(owidProcessingLevel)

const attributionFragments = attributions ?? producersWithYear
const attributionPotentiallyShortened =
attributionFragments.length > 3
? `${attributionFragments[0]} and other sources`
: attributionFragments.join("; ")

return `${attributionPotentiallyShortened}${processingLevelPhrase} by Our World in Data`
}

export const getCitationLong = (
indicatorTitle: IndicatorTitleWithFragments,
origins: OwidOrigin[],
source: OwidSource | undefined,
attributions: string[],
attributionShort: string | undefined,
titleVariant: string | undefined,
owidProcessingLevel: OwidProcessingLevel | undefined,
canonicalUrl: string | undefined
): string => {
const sourceShortName =
attributionShort && titleVariant
? `${attributionShort}${titleVariant}`
: attributionShort || titleVariant
const producersWithYear = uniq(
origins.map((o) => `${o.producer}${getYearSuffixFromOrigin(o)}`)
)
const processingLevelPhrase =
getPhraseForProcessingLevel(owidProcessingLevel)

const attributionFragments = attributions ?? producersWithYear
const attributionUnshortened = attributionFragments.join("; ")
const citationLonger = `${attributionUnshortened}${processingLevelPhrase} by Our World in Data`
const titleWithOptionalFragments = excludeUndefined([
indicatorTitle.title,
sourceShortName,
]).join(" – ")
const originsLong = uniq(
origins.map(
(o) =>
`${o.producer}, “${o.title ?? o.titleSnapshot}${
o.versionProducer ? " " + o.versionProducer : ""
}”`
)
).join("; ")
const today = dayjs().format("MMMM D, YYYY")
return excludeUndefined([
`${citationLonger}.`,
`“${titleWithOptionalFragments}” [dataset].`,
originsLong
? `${originsLong} [original data].`
: source?.name
? `${source?.name} [original data].`
: undefined,
canonicalUrl ? `Retrieved ${today} from ${canonicalUrl}` : undefined,
]).join(" ")
}
export const formatSourceDate = (
date: string | undefined,
format: string
Expand Down
Loading

0 comments on commit f4ab296

Please sign in to comment.