diff --git a/components/article/ArticlePage.tsx b/components/article/ArticlePage.tsx
new file mode 100644
index 0000000000..ac4cdfaec2
--- /dev/null
+++ b/components/article/ArticlePage.tsx
@@ -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 (
+
+
+
+
+
+
+
+
{title}
+
+ {contributor && (
+
+ )}
+
+ {intro && (
+
+ )}
+
+ {permissions && (
+
+ )}
+
+ {includesPlatformSpecificContent && (
+
+ )}
+
+ {product && (
+
+ )}
+
+
+
+
+ {miniTocItems.length > 1 && (
+ <>
+
+
+ {miniTocItems.map((item) => {
+ return (
+
+ )
+ })}
+
+ >
+ )}
+
+
+
+
+
+
+ {currentLearningTrack?.trackName ? (
+
+
+
+ ) : null}
+
+
+
+ )
+}
diff --git a/components/article/ArticleTitle.tsx b/components/article/ArticleTitle.tsx
index 52a0789c59..c9a74e8efe 100644
--- a/components/article/ArticleTitle.tsx
+++ b/components/article/ArticleTitle.tsx
@@ -7,7 +7,7 @@ type Props = {
export const ArticleTitle = ({ children }: Props) => {
return (
-
{children}
+
{children}
+ )
+}
diff --git a/components/context/ArticleContext.tsx b/components/context/ArticleContext.tsx
new file mode 100644
index 0000000000..c3f898bf16
--- /dev/null
+++ b/components/context/ArticleContext.tsx
@@ -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
+ contributor: { name: string; URL: string } | null
+ permissions?: string
+ includesPlatformSpecificContent: boolean
+ defaultPlatform?: string
+ product?: string
+ currentLearningTrack?: LearningTrack
+}
+
+export const ArticleContext = createContext(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,
+ }
+}
diff --git a/data/ui.yml b/data/ui.yml
index a904b4c35d..75b548ee5e 100644
--- a/data/ui.yml
+++ b/data/ui.yml
@@ -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
diff --git a/includes/article.html b/includes/article.html
index 0277c0bb50..c06e41412d 100644
--- a/includes/article.html
+++ b/includes/article.html
@@ -22,7 +22,7 @@
{% if page.contributor %}
{% endif %}
diff --git a/lib/page.js b/lib/page.js
index 71ea17141a..5344462355 100644
--- a/lib/page.js
+++ b/lib/page.js
@@ -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 })
diff --git a/middleware/render-page.js b/middleware/render-page.js
index 43e4ed4caf..4f44511e0d 100644
--- a/middleware/render-page.js
+++ b/middleware/render-page.js
@@ -171,7 +171,7 @@ module.exports = async function renderPage (req, res, next) {
}
// Create string for tag
- context.page.fullTitle = context.page.title
+ context.page.fullTitle = context.page.titlePlainText
// add localized ` - GitHub Docs` suffix to 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)
}
diff --git a/pages/[versionId]/[productId]/index.tsx b/pages/[versionId]/[productId]/index.tsx
index 2ba64d13b6..c0af21516e 100644
--- a/pages/[versionId]/[productId]/index.tsx
+++ b/pages/[versionId]/[productId]/index.tsx
@@ -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
)
} else {
- content = article / fallback rendering
+ content = (
+
+
+
+ )
}
return {content}
@@ -65,6 +83,7 @@ export const getServerSideProps: GetServerSideProps = async (context) =>
mainContext: getMainContextFromRequest(req),
productLandingContext: getProductLandingContextFromRequest(req),
tocLandingContext: getTocLandingContextFromRequest(req),
+ articleContext: getArticleContextFromRequest(req),
},
}
}