1
0
mirror of synced 2026-01-29 12:00:58 -05:00

Merge pull request #7161 from github/repo-sync

repo sync
This commit is contained in:
Octomerger Bot
2021-06-08 09:22:01 +10:00
committed by GitHub
9 changed files with 282 additions and 6 deletions

View File

@@ -0,0 +1,152 @@
import cx from 'classnames'
import { DefaultLayout } from 'components/DefaultLayout'
import { ArticleVersionPicker } from 'components/article/ArticleVersionPicker'
import { Breadcrumbs } from 'components/Breadcrumbs'
import { ArticleTitle } from 'components/article/ArticleTitle'
import { useArticleContext } from 'components/context/ArticleContext'
import { InfoIcon } from '@primer/octicons-react'
import { useTranslation } from 'components/hooks/useTranslation'
import { LearningTrackNav } from './LearningTrackNav'
export const ArticlePage = () => {
const {
title,
intro,
renderedPage,
contributor,
permissions,
includesPlatformSpecificContent,
defaultPlatform,
product,
miniTocItems,
currentLearningTrack,
} = useArticleContext()
const { t } = useTranslation('pages')
return (
<DefaultLayout>
<div className="container-xl px-3 px-md-6 my-4 my-lg-4">
<article className="markdown-body">
<div className="d-lg-flex flex-justify-between">
<div className="d-block d-lg-none">
<ArticleVersionPicker />
</div>
<div className="d-flex flex-items-center">
<Breadcrumbs />
</div>
<div className="d-none d-lg-block">
<ArticleVersionPicker />
</div>
</div>
<div className="article-grid-container mt-2">
<div className="article-grid-head">
<ArticleTitle>{title}</ArticleTitle>
{contributor && (
<div className="contributor-callout border rounded-1 mb-4 p-3 color-border-info color-bg-info f5">
<p>
<span className="mr-2">
<InfoIcon />
</span>
{t('contributor_callout')} <a href={contributor.URL}>{contributor.name}</a>.
</p>
</div>
)}
{intro && (
<div className="lead-mktg">
<p>{intro}</p>
</div>
)}
{permissions && (
<div
className="permissions-statement"
dangerouslySetInnerHTML={{ __html: permissions }}
/>
)}
{includesPlatformSpecificContent && (
<nav
className="UnderlineNav my-3"
data-default-platform={defaultPlatform || undefined}
>
<div className="UnderlineNav-body">
<a href="#" className="UnderlineNav-item platform-switcher" data-platform="mac">
Mac
</a>
<a
href="#"
className="UnderlineNav-item platform-switcher"
data-platform="windows"
>
Windows
</a>
<a
href="#"
className="UnderlineNav-item platform-switcher"
data-platform="linux"
>
Linux
</a>
</div>
</nav>
)}
{product && (
<div
className="product-callout border rounded-1 mb-4 p-3 color-border-success color-bg-success"
dangerouslySetInnerHTML={{ __html: product }}
/>
)}
</div>
<div className="article-grid-toc border-bottom border-xl-0 pb-4 mb-5 pb-xl-0 mb-xl-0">
<div className="article-grid-toc-content">
{miniTocItems.length > 1 && (
<>
<h2 id="in-this-article" className="f5 mb-2">
<a className="Link--primary" href="#in-this-article">
{t('miniToc')}
</a>
</h2>
<ul className="list-style-none pl-0 f5 mb-0">
{miniTocItems.map((item) => {
return (
<li
key={item.contents}
className={cx(
`ml-${item.indentationLevel * 3}`,
item.platform,
'mb-2 lh-condensed'
)}
dangerouslySetInnerHTML={{ __html: item.contents }}
/>
)
})}
</ul>
</>
)}
</div>
</div>
<div className="markdown-body">
<div
id="article-contents"
className="article-grid-body"
dangerouslySetInnerHTML={{ __html: renderedPage }}
/>
</div>
</div>
{currentLearningTrack?.trackName ? (
<div className="d-block mt-4 markdown-body">
<LearningTrackNav track={currentLearningTrack} />
</div>
) : null}
</article>
</div>
</DefaultLayout>
)
}

View File

@@ -7,7 +7,7 @@ type Props = {
export const ArticleTitle = ({ children }: Props) => {
return (
<div className="d-flex flex-items-baseline flex-justify-between">
<h1 className="my-4">{children}</h1>
<h1 className="my-4 border-bottom-0">{children}</h1>
<div className="d-none d-lg-block ml-2">
<Tooltip aria-label="Print this article" noDelay direction="n">
<Link

View File

@@ -0,0 +1,41 @@
import type { LearningTrack } from 'components/context/ArticleContext'
import { useTranslation } from 'components/hooks/useTranslation'
type Props = {
track: LearningTrack
}
export function LearningTrackNav({ track }: Props) {
const { t } = useTranslation('learning_track_nav')
const { prevGuide, nextGuide, trackName } = track
return (
<div className="py-3 px-4 rounded color-bg-primary border-gradient--purple-pink d-flex flex-justify-between learning-track-nav">
<span className="d-flex flex-column">
{prevGuide && (
<>
<span className="f6 color-text-secondary">{t('prevGuide')}</span>
<a
href={`${prevGuide.href}?learn=${trackName}`}
className="text-bold color-text-secondary"
>
{prevGuide.title}
</a>
</>
)}
</span>
<span className="d-flex flex-column flex-items-end">
{nextGuide && (
<>
<span className="f6 color-text-secondary">{t('nextGuide')}</span>
<a
href={`${nextGuide.href}?learn=${trackName}`}
className="text-bold color-text-secondary text-right"
>
{nextGuide.title}
</a>
</>
)}
</span>
</div>
)
}

View File

@@ -0,0 +1,61 @@
import { createContext, useContext } from 'react'
export type LearningTrack = {
trackName?: string
prevGuide?: { href: string; title: string }
nextGuide?: { href: string; title: string }
}
export type MiniTocItem = {
indentationLevel: number
platform: string
contents: string
}
export type ArticleContextT = {
title: string
intro: string
renderedPage: string
miniTocItems: Array<MiniTocItem>
contributor: { name: string; URL: string } | null
permissions?: string
includesPlatformSpecificContent: boolean
defaultPlatform?: string
product?: string
currentLearningTrack?: LearningTrack
}
export const ArticleContext = createContext<ArticleContextT | null>(null)
export const useArticleContext = (): ArticleContextT => {
const context = useContext(ArticleContext)
if (!context) {
throw new Error('"useArticleContext" may only be used inside "ArticleContext.Provider"')
}
return context
}
export const getArticleContextFromRequest = (req: any): ArticleContextT => {
const page = req.context.page
return {
title: page.titlePlainText,
intro: page.introPlainText,
renderedPage: req.context.renderedPage || '',
miniTocItems:
(req.context.miniTocItems || []).map((item: any) => {
return {
indentationLevel: item.indentationLevel || 0,
platform: item.platform || '',
contents: item.contents || '',
}
}) || [],
contributor: page.contributor || null,
permissions: page.permissions || '',
includesPlatformSpecificContent: page.includesPlatformSpecificContent || false,
defaultPlatform: page.defaultPlatform || '',
product: page.product || '',
currentLearningTrack: req.context.currentLearningTrack,
}
}

View File

@@ -40,6 +40,7 @@ toc:
pages:
article_version: 'Article version:'
miniToc: In this article
contributor_callout: This article is contributed and maintained by
errors:
oops: Ooops!
something_went_wrong: It looks like something went wrong.
@@ -176,7 +177,6 @@ product_sublanding:
learning_track_nav:
prevGuide: Previous guide
nextGuide: Next guide
contributor_callout: This article is contributed and maintained by
toggle_images:
off: Images are off, click to show
on: Images are on, click to hide

View File

@@ -22,7 +22,7 @@
{% if page.contributor %}
<div class="contributor-callout border rounded-1 mb-4 p-3 color-border-info color-bg-info f5">
<p><span class="mr-2">{% octicon "info" %}</span>{% data ui.contributor_callout %} <a href="{{ page.contributor.URL }}">{{ page.contributor.name }}</a>.</p>
<p><span class="mr-2">{% octicon "info" %}</span>{% data ui.pages.contributor_callout %} <a href="{{ page.contributor.URL }}">{{ page.contributor.name }}</a>.</p>
</div>
{% endif %}

View File

@@ -158,6 +158,7 @@ class Page {
this.intro = await renderContent(this.rawIntro, context)
this.introPlainText = await renderContent(this.rawIntro, context, { textOnly: true })
this.title = await renderContent(this.rawTitle, context, { textOnly: true, encodeEntities: true })
this.titlePlainText = await renderContent(this.rawTitle, context, { textOnly: true })
this.shortTitle = await renderContent(this.shortTitle, context, { textOnly: true, encodeEntities: true })
this.product_video = await renderContent(this.raw_product_video, context, { textOnly: true })

View File

@@ -171,7 +171,7 @@ module.exports = async function renderPage (req, res, next) {
}
// Create string for <title> tag
context.page.fullTitle = context.page.title
context.page.fullTitle = context.page.titlePlainText
// add localized ` - GitHub Docs` suffix to <title> tag (except for the homepage)
if (!patterns.homepagePath.test(req.path)) {
@@ -194,6 +194,8 @@ module.exports = async function renderPage (req, res, next) {
// Hand rendering over to NextJS when appropriate
if (renderWithNextjs) {
req.context.renderedPage = context.renderedPage
req.context.miniTocItems = context.miniTocItems
return nextHandleRequest(req, res)
}

View File

@@ -5,12 +5,20 @@ import {
MainContext,
getMainContextFromRequest,
} from 'components/context/MainContext'
import {
getProductLandingContextFromRequest,
ProductLandingContextT,
ProductLandingContext,
} from 'components/context/ProductLandingContext'
import {
getArticleContextFromRequest,
ArticleContextT,
ArticleContext,
} from 'components/context/ArticleContext'
import { ArticlePage } from 'components/article/ArticlePage'
import { ProductLanding } from 'components/landing/ProductLanding'
import { TocLanding } from 'components/landing/TocLanding'
import {
@@ -23,8 +31,14 @@ type Props = {
mainContext: MainContextT
productLandingContext: ProductLandingContextT
tocLandingContext: TocLandingContextT
articleContext: ArticleContextT
}
const GlobalPage = ({ mainContext, productLandingContext, tocLandingContext }: Props) => {
const GlobalPage = ({
mainContext,
productLandingContext,
tocLandingContext,
articleContext,
}: Props) => {
const { currentLayoutName, page, relativePath } = mainContext
let content
@@ -49,7 +63,11 @@ const GlobalPage = ({ mainContext, productLandingContext, tocLandingContext }: P
</TocLandingContext.Provider>
)
} else {
content = <p>article / fallback rendering</p>
content = (
<ArticleContext.Provider value={articleContext}>
<ArticlePage />
</ArticleContext.Provider>
)
}
return <MainContext.Provider value={mainContext}>{content}</MainContext.Provider>
@@ -65,6 +83,7 @@ export const getServerSideProps: GetServerSideProps<Props> = async (context) =>
mainContext: getMainContextFromRequest(req),
productLandingContext: getProductLandingContextFromRequest(req),
tocLandingContext: getTocLandingContextFromRequest(req),
articleContext: getArticleContextFromRequest(req),
},
}
}