1
0
mirror of synced 2025-12-23 11:54:18 -05:00

Scope markdown body (#21082)

* update article content to markdown ui component

* decouple lunr indexing from class name

* remove summary outline none rule, apply utility class instead

* improve typing

* scope more styles down to markdown-body/extended-markdown

* move all markdown-body style overrides to MarkdownContent component

* fix class targeting within css module

* clean up MarkdownContent header style

* rename data-lunr to data-search

* fix: inline code color issue

* fix: update article markdown to work with MarkdownContent
This commit is contained in:
Mike Surowiec
2021-08-30 10:24:49 -04:00
committed by GitHub
parent 0e31d4aaa4
commit d76c16da19
35 changed files with 472 additions and 449 deletions

View File

@@ -1,15 +1,14 @@
import React, { ReactNode, ReactHTML } from 'react' import React, { ReactNode } from 'react'
import cx from 'classnames' import cx from 'classnames'
type Props = { type Props = {
as?: keyof ReactHTML as?: keyof JSX.IntrinsicElements
maxLines: number maxLines: number
children: ReactNode children: ReactNode
className?: string className?: string
} }
export const TruncateLines = (props: Props) => { export const TruncateLines = (props: Props) => {
const { as, maxLines, className, children } = props const { maxLines, className, children, as: Component = 'div' } = props
const Component = as || 'div'
return ( return (
<Component className={cx('root', className)}> <Component className={cx('root', className)}>
{children} {children}

View File

@@ -1,18 +0,0 @@
type Props = {
children: string
}
/*
NOTE: The markdown-body class is used by the LUNR search scripts.
If this class changes, please also change
updating script/search/parse-page-sections-into-records.js.
*/
export const ArticleContent = ({ children }: Props) => {
return (
<div
id="article-contents"
className="markdown-body"
dangerouslySetInnerHTML={{ __html: children }}
/>
)
}

View File

@@ -22,12 +22,9 @@ export const ArticleGridLayout = ({ head, toc, children, className }: Props) =>
)} )}
{/* content */} {/* content */}
{/* <div data-search="article-body" className={styles.content}>
NOTE: The article-grid-body class is used by the LUNR search scripts. {children}
If this class changes, please also change </div>
updating script/search/parse-page-sections-into-records.js.
*/}
<div className={cx(styles.content, 'article-grid-body')}>{children}</div>
</div> </div>
) )
} }

View File

@@ -11,7 +11,7 @@ import { ArticleTitle } from 'components/article/ArticleTitle'
import { useArticleContext } from 'components/context/ArticleContext' import { useArticleContext } from 'components/context/ArticleContext'
import { useTranslation } from 'components/hooks/useTranslation' import { useTranslation } from 'components/hooks/useTranslation'
import { LearningTrackNav } from './LearningTrackNav' import { LearningTrackNav } from './LearningTrackNav'
import { ArticleContent } from './ArticleContent' import { MarkdownContent } from 'components/ui/MarkdownContent'
import { ArticleGridLayout } from './ArticleGridLayout' import { ArticleGridLayout } from './ArticleGridLayout'
// Mapping of a "normal" article to it's interactive counterpart // Mapping of a "normal" article to it's interactive counterpart
@@ -63,12 +63,7 @@ export const ArticlePage = () => {
</Callout> </Callout>
)} )}
{intro && ( {intro && <MarkdownContent className="lead-mktg mb-3">{intro}</MarkdownContent>}
<div
className="lead-mktg markdown-body mb-3"
dangerouslySetInnerHTML={{ __html: intro }}
/>
)}
{permissions && ( {permissions && (
<div <div
@@ -153,7 +148,9 @@ export const ArticlePage = () => {
</> </>
} }
> >
<ArticleContent>{renderedPage}</ArticleContent> <div id="article-contents">
<MarkdownContent>{renderedPage}</MarkdownContent>
</div>
</ArticleGridLayout> </ArticleGridLayout>
{currentLearningTrack?.trackName ? ( {currentLearningTrack?.trackName ? (

View File

@@ -25,7 +25,7 @@ export const ArticleVersionPicker = () => {
`} `}
data-testid="article-version-picker" data-testid="article-version-picker"
> >
<summary className="f4 h5-mktg btn-outline-mktg btn-mktg p-2"> <summary className="f4 h5-mktg btn-outline-mktg btn-mktg p-2 outline-none">
<span className="d-md-none d-xl-inline-block">{t('article_version')}</span>{' '} <span className="d-md-none d-xl-inline-block">{t('article_version')}</span>{' '}
{allVersions[currentVersion].versionTitle} {allVersions[currentVersion].versionTitle}
<Dropdown.Caret /> <Dropdown.Caret />

View File

@@ -25,7 +25,7 @@ export const HomepageVersionPicker = ({ variant }: Props) => {
if (variant === 'inline') { if (variant === 'inline') {
return ( return (
<Details {...getDetailsProps()} className="details-reset"> <Details {...getDetailsProps()} className="details-reset">
<summary aria-label="Toggle language list"> <summary className="outline-none" aria-label="Toggle language list">
<div className="d-flex flex-items-center flex-justify-between py-2"> <div className="d-flex flex-items-center flex-justify-between py-2">
<span>{label}</span> <span>{label}</span>
<ChevronDownIcon size={24} className="arrow ml-md-1" /> <ChevronDownIcon size={24} className="arrow ml-md-1" />

View File

@@ -3,7 +3,7 @@ import { TableOfContents } from 'components/landing/TableOfContents'
import { useTocLandingContext } from 'components/context/TocLandingContext' import { useTocLandingContext } from 'components/context/TocLandingContext'
import { ArticleTopper } from 'components/article/ArticleTopper' import { ArticleTopper } from 'components/article/ArticleTopper'
import { ArticleTitle } from 'components/article/ArticleTitle' import { ArticleTitle } from 'components/article/ArticleTitle'
import { ArticleContent } from 'components/article/ArticleContent' import { MarkdownContent } from 'components/ui/MarkdownContent'
import { ArticleList } from 'components/landing/ArticleList' import { ArticleList } from 'components/landing/ArticleList'
import { useTranslation } from 'components/hooks/useTranslation' import { useTranslation } from 'components/hooks/useTranslation'
import { ArticleGridLayout } from 'components/article/ArticleGridLayout' import { ArticleGridLayout } from 'components/article/ArticleGridLayout'
@@ -55,7 +55,11 @@ export const TocLanding = () => {
</div> </div>
)} )}
{renderedPage && <ArticleContent>{renderedPage}</ArticleContent>} {renderedPage && (
<div id="article-contents">
<MarkdownContent>{renderedPage}</MarkdownContent>
</div>
)}
<TableOfContents items={tocItems} variant={variant} /> <TableOfContents items={tocItems} variant={variant} />
</div> </div>

View File

@@ -3,7 +3,7 @@ import parseUserAgent from './user-agent'
import { sendEvent, EventType } from './events' import { sendEvent, EventType } from './events'
const supportedPlatforms = ['mac', 'windows', 'linux'] const supportedPlatforms = ['mac', 'windows', 'linux']
const detectedPlatforms = new Set() const detectedPlatforms = new Set<string>()
// Emphasize content for the visitor's OS (inferred from user agent string) // Emphasize content for the visitor's OS (inferred from user agent string)
@@ -66,9 +66,7 @@ function setActiveSwitcherLinks(platform: string) {
function showPlatformSpecificContent(platform: string) { function showPlatformSpecificContent(platform: string) {
// find all platform-specific *block* elements and hide or show as appropriate // find all platform-specific *block* elements and hide or show as appropriate
// example: {{ #mac }} block content {{/mac}} // example: {{ #mac }} block content {{/mac}}
const markdowns = Array.from( const markdowns = Array.from(document.querySelectorAll<HTMLElement>('.extended-markdown'))
document.querySelectorAll('.extended-markdown')
) as Array<HTMLElement>
markdowns markdowns
.filter((el) => supportedPlatforms.some((platform) => el.classList.contains(platform))) .filter((el) => supportedPlatforms.some((platform) => el.classList.contains(platform)))
.forEach((el) => { .forEach((el) => {
@@ -78,8 +76,8 @@ function showPlatformSpecificContent(platform: string) {
// find all platform-specific *inline* elements and hide or show as appropriate // find all platform-specific *inline* elements and hide or show as appropriate
// example: <span class="platform-mac">inline content</span> // example: <span class="platform-mac">inline content</span>
const platforms = Array.from( const platforms = Array.from(
document.querySelectorAll('.platform-mac, .platform-windows, .platform-linux') document.querySelectorAll<HTMLElement>('.platform-mac, .platform-windows, .platform-linux')
) as Array<HTMLElement> )
platforms.forEach((el) => { platforms.forEach((el) => {
el.style.display = el.classList.contains('platform-' + platform) ? '' : 'none' el.style.display = el.classList.contains('platform-' + platform) ? '' : 'none'
}) })
@@ -108,11 +106,11 @@ function getDetectedPlatforms(): Array<string> {
// find all platform-specific *inline* elements and hide or show as appropriate // find all platform-specific *inline* elements and hide or show as appropriate
// example: <span class="platform-mac">inline content</span> // example: <span class="platform-mac">inline content</span>
const platformEls = Array.from( const platformEls = Array.from(
document.querySelectorAll('.platform-mac, .platform-windows, .platform-linux') document.querySelectorAll<HTMLElement>('.platform-mac, .platform-windows, .platform-linux')
) as Array<HTMLElement> )
platformEls.forEach((el) => detectPlatforms(el)) platformEls.forEach((el) => detectPlatforms(el))
return Array.from(detectedPlatforms) as Array<string> return Array.from(detectedPlatforms)
} }
function detectPlatforms(el: HTMLElement) { function detectPlatforms(el: HTMLElement) {

View File

@@ -20,7 +20,7 @@ export const LanguagePicker = ({ variant }: Props) => {
if (variant === 'inline') { if (variant === 'inline') {
return ( return (
<Details {...getDetailsProps()} className="details-reset"> <Details {...getDetailsProps()} className="details-reset">
<summary aria-label="Toggle language list"> <summary className="outline-none" aria-label="Toggle language list">
<div className="d-flex flex-items-center flex-justify-between py-2"> <div className="d-flex flex-items-center flex-justify-between py-2">
<span>{selectedLang.nativeName || selectedLang.name}</span> <span>{selectedLang.nativeName || selectedLang.name}</span>
<ChevronDownIcon size={24} className="arrow ml-md-1" /> <ChevronDownIcon size={24} className="arrow ml-md-1" />

View File

@@ -13,7 +13,11 @@ export const ProductPicker = () => {
return ( return (
<Details {...getDetailsProps()} className="details-reset"> <Details {...getDetailsProps()} className="details-reset">
<summary className="color-text-link" role="button" aria-label="Toggle products list"> <summary
className="color-text-link outline-none"
role="button"
aria-label="Toggle products list"
>
<div id="current-product" className="d-flex flex-items-center flex-justify-between py-2"> <div id="current-product" className="d-flex flex-items-center flex-justify-between py-2">
{/* <!-- Product switcher - GitHub.com, Enterprise Server, etc --> {/* <!-- Product switcher - GitHub.com, Enterprise Server, etc -->
<!-- 404 and 500 error layouts are not real pages so we need to hardcode the name for those --> */} <!-- 404 and 500 error layouts are not real pages so we need to hardcode the name for those --> */}

View File

@@ -0,0 +1,10 @@
.articleMarkdown {
pre {
padding: 0;
background-color: unset;
}
table {
table-layout: fixed !important;
}
}

View File

@@ -1,10 +1,15 @@
import React from 'react' import React from 'react'
import cx from 'classnames'
import { useTheme } from '@primer/components' import { useTheme } from '@primer/components'
import ReactMarkdown from 'react-markdown' import ReactMarkdown from 'react-markdown'
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter' import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
import { vs, vscDarkPlus } from 'react-syntax-highlighter/dist/cjs/styles/prism' import { vs, vscDarkPlus } from 'react-syntax-highlighter/dist/cjs/styles/prism'
import gfm from 'remark-gfm' import gfm from 'remark-gfm'
import { MarkdownContent } from 'components/ui/MarkdownContent'
import styles from './ArticleMarkdown.module.scss'
type Props = { type Props = {
className?: string className?: string
children: string children: string
@@ -13,30 +18,32 @@ export const ArticleMarkdown = ({ className, children }: Props) => {
const theme = useTheme() const theme = useTheme()
return ( return (
<ReactMarkdown <MarkdownContent>
className={className} <ReactMarkdown
remarkPlugins={[gfm as any]} className={cx(styles.articleMarkdown, className)}
components={{ remarkPlugins={[gfm as any]}
// eslint-disable-next-line @typescript-eslint/no-unused-vars components={{
code: ({ node, inline, className, children, ...props }) => { // eslint-disable-next-line @typescript-eslint/no-unused-vars
const match = /language-(\w+)/.exec(className || '') code: ({ node, inline, className, children, ...props }) => {
return !inline && match ? ( const match = /language-(\w+)/.exec(className || '')
<SyntaxHighlighter return !inline && match ? (
style={theme.colorScheme === 'dark' ? vscDarkPlus : vs} <SyntaxHighlighter
language={match[1]} style={theme.colorScheme === 'dark' ? vscDarkPlus : vs}
PreTag="div" language={match[1]}
children={String(children).replace(/\n$/, '')} PreTag="div"
{...(props as any)} children={String(children).replace(/\n$/, '')}
/> {...(props as any)}
) : ( />
<code className={className} {...props}> ) : (
{children} <code className={className} {...props}>
</code> {children}
) </code>
}, )
}} },
> }}
{children} >
</ReactMarkdown> {children}
</ReactMarkdown>
</MarkdownContent>
) )
} }

View File

@@ -3,6 +3,7 @@ import cx from 'classnames'
import { ChevronDownIcon } from '@primer/octicons-react' import { ChevronDownIcon } from '@primer/octicons-react'
import { GHAEReleaseNotePatch } from './GHAEReleaseNotePatch' import { GHAEReleaseNotePatch } from './GHAEReleaseNotePatch'
import { GHAEReleaseNotesContextT } from './types' import { GHAEReleaseNotesContextT } from './types'
import { MarkdownContent } from 'components/ui/MarkdownContent'
type GitHubAEProps = { type GitHubAEProps = {
context: GHAEReleaseNotesContextT context: GHAEReleaseNotesContextT
@@ -20,7 +21,7 @@ export function GHAEReleaseNotes({ context }: GitHubAEProps) {
<div></div> <div></div>
</div> </div>
<div className="markdown-body"> <MarkdownContent data-search="article-content">
{releaseNotes.map((patch) => { {releaseNotes.map((patch) => {
return ( return (
<GHAEReleaseNotePatch <GHAEReleaseNotePatch
@@ -30,25 +31,27 @@ export function GHAEReleaseNotes({ context }: GitHubAEProps) {
/> />
) )
})} })}
</div> </MarkdownContent>
</article> </article>
<aside <aside
className="markdown-body position-sticky top-0 d-none d-md-block border-left no-print color-bg-primary flex-shrink-0" className="position-sticky top-0 d-none d-md-block border-left no-print color-bg-primary flex-shrink-0"
style={{ width: 260, height: '100vh' }} style={{ width: 260, height: '100vh' }}
> >
<nav className="height-full overflow-auto"> <nav className="height-full overflow-auto">
<ul className="list-style-none pl-0 text-bold"> <MarkdownContent data-search="article-content">
{releases.map((release) => { <ul className="list-style-none pl-0 text-bold">
return ( {releases.map((release) => {
<CollapsibleReleaseSection return (
key={release.version} <CollapsibleReleaseSection
release={release} key={release.version}
focusedPatch={focusedPatch} release={release}
/> focusedPatch={focusedPatch}
) />
})} )
</ul> })}
</ul>
</MarkdownContent>
</nav> </nav>
</aside> </aside>
</div> </div>
@@ -78,7 +81,7 @@ const CollapsibleReleaseSection = ({
open={defaultIsOpen} open={defaultIsOpen}
onToggle={onToggle} onToggle={onToggle}
> >
<summary className="px-3 py-4 my-0 d-flex flex-items-center flex-justify-between"> <summary className="px-3 py-4 my-0 d-flex flex-items-center flex-justify-between outline-none">
{release.version} {release.version}
<div className="d-flex"> <div className="d-flex">
<span className="color-text-tertiary text-mono text-small text-normal mr-1"> <span className="color-text-tertiary text-mono text-small text-normal mr-1">

View File

@@ -10,6 +10,7 @@ import { useMainContext } from 'components/context/MainContext'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { Link } from 'components/Link' import { Link } from 'components/Link'
import { MarkdownContent } from 'components/ui/MarkdownContent'
import { GHESReleaseNotesContextT } from './types' import { GHESReleaseNotesContextT } from './types'
import { GHESReleaseNotePatch } from './GHESReleaseNotePatch' import { GHESReleaseNotePatch } from './GHESReleaseNotePatch'
@@ -59,7 +60,7 @@ export function GHESReleaseNotes({ context }: Props) {
<div /> <div />
)} )}
</div> </div>
<div className="markdown-body"> <MarkdownContent data-search="article-content">
{releaseNotes.map((patch) => { {releaseNotes.map((patch) => {
return ( return (
<GHESReleaseNotePatch <GHESReleaseNotePatch
@@ -75,58 +76,60 @@ export function GHESReleaseNotes({ context }: Props) {
/> />
) )
})} })}
</div> </MarkdownContent>
</article> </article>
<aside <aside
className="markdown-body position-sticky top-0 d-none d-md-block border-left no-print color-bg-primary flex-shrink-0" className="position-sticky top-0 d-none d-md-block border-left no-print color-bg-primary flex-shrink-0"
style={{ width: 260, height: '100vh' }} style={{ width: 260, height: '100vh' }}
> >
<nav className="height-full overflow-auto"> <nav className="height-full overflow-auto">
<ul className="list-style-none pl-0 text-bold"> <MarkdownContent data-search="article-content">
{releases.map((release) => { <ul className="list-style-none pl-0 text-bold">
const releaseLink = `/${currentLanguage}/${currentVersion.plan}@${release.version}/${currentProduct?.id}/release-notes` {releases.map((release) => {
const releaseLink = `/${currentLanguage}/${currentVersion.plan}@${release.version}/${currentProduct?.id}/release-notes`
if (!release.patches || release.patches.length === 0) {
return (
<li key={release.version} className="border-bottom">
<Link
href={releaseLink}
className="Link--primary no-underline px-3 py-4 my-0 d-flex flex-items-center flex-justify-between"
>
{release.version}
<LinkExternalIcon />
</Link>
</li>
)
}
if (release.version === currentVersion.currentRelease) {
return (
<CollapsibleReleaseSection
key={release.version}
release={release}
focusedPatch={focusedPatch}
releaseLink={releaseLink}
/>
)
}
if (!release.patches || release.patches.length === 0) {
return ( return (
<li key={release.version} className="border-bottom"> <li key={release.version} className="border-bottom">
<Link <Link
className="px-3 py-4 my-0 d-flex flex-items-center flex-justify-between"
href={releaseLink} href={releaseLink}
className="Link--primary no-underline px-3 py-4 my-0 d-flex flex-items-center flex-justify-between"
> >
{release.version} {release.version}
<LinkExternalIcon /> <span className="color-text-tertiary text-mono text-small text-normal mr-1">
{release.patches.length} releases
</span>
</Link> </Link>
</li> </li>
) )
} })}
</ul>
if (release.version === currentVersion.currentRelease) { </MarkdownContent>
return (
<CollapsibleReleaseSection
key={release.version}
release={release}
focusedPatch={focusedPatch}
releaseLink={releaseLink}
/>
)
}
return (
<li key={release.version} className="border-bottom">
<Link
className="px-3 py-4 my-0 d-flex flex-items-center flex-justify-between"
href={releaseLink}
>
{release.version}
<span className="color-text-tertiary text-mono text-small text-normal mr-1">
{release.patches.length} releases
</span>
</Link>
</li>
)
})}
</ul>
</nav> </nav>
</aside> </aside>
</div> </div>
@@ -157,7 +160,7 @@ const CollapsibleReleaseSection = ({
open={defaultIsOpen} open={defaultIsOpen}
onToggle={onToggle} onToggle={onToggle}
> >
<summary className="px-3 py-4 my-0 d-flex flex-items-center flex-justify-between"> <summary className="px-3 py-4 my-0 d-flex flex-items-center flex-justify-between outline-none">
{release.version} {release.version}
<div className="d-flex"> <div className="d-flex">
<span className="color-text-tertiary text-mono text-small text-normal mr-1"> <span className="color-text-tertiary text-mono text-small text-normal mr-1">

View File

@@ -140,7 +140,7 @@ const CollapsibleSection = (props: SectionProps) => {
return ( return (
<details open={defaultOpen} onToggle={onToggle} className="details-reset"> <details open={defaultOpen} onToggle={onToggle} className="details-reset">
<summary> <summary className="outline-none">
<div className="d-flex flex-justify-between"> <div className="d-flex flex-justify-between">
<div className="pl-4 pr-1 py-2 f6 text-uppercase d-block flex-auto mr-3 color-text-primary no-underline text-bold"> <div className="pl-4 pr-1 py-2 f6 text-uppercase d-block flex-auto mr-3 color-text-primary no-underline text-bold">
{title} {title}

View File

@@ -0,0 +1,37 @@
@import "./stylesheets/code.scss";
@import "./stylesheets/headers.scss";
@import "./stylesheets/lists.scss";
@import "./stylesheets/table.scss";
.markdownBody {
summary {
outline: none;
h1,
h2,
h3,
h4,
h5,
h6 {
display: inline-block;
margin-top: 10px;
margin-bottom: 10px;
p {
margin: 0;
padding: 0;
}
}
}
[class~="note"],
[class~="tip"],
[class~="warning"],
[class~="danger"] {
// remove extra space under lists inside of notes
ul,
ol {
margin-bottom: 0;
}
}
}

View File

@@ -0,0 +1,26 @@
import { ReactNode } from 'react'
import cx from 'classnames'
import styles from './MarkdownContent.module.scss'
type Props = {
children: string | ReactNode
className?: string
as?: keyof JSX.IntrinsicElements
}
export const MarkdownContent = ({
children,
as: Component = 'div',
className,
...restProps
}: Props) => {
return (
<Component
{...restProps}
className={cx(styles.markdownBody, 'markdown-body', className)}
{...(typeof children === 'string'
? { dangerouslySetInnerHTML: { __html: children } }
: { children })}
/>
)
}

View File

@@ -0,0 +1 @@
export { MarkdownContent } from './MarkdownContent'

View File

@@ -0,0 +1,45 @@
.markdownBody {
[class~="highlight"] pre,
pre {
margin-top: 10px;
}
[class~="height-constrained-code-block"] pre {
max-height: 500px;
overflow: auto;
}
[class~="code-extra"] {
margin-top: 24px;
pre {
margin-top: 0 !important;
border-top-left-radius: 0 !important;
border-top-right-radius: 0 !important;
border-left: 1px var(--color-auto-gray-2) solid !important;
border-bottom: 1px var(--color-auto-gray-2) solid !important;
border-right: 1px var(--color-auto-gray-2) solid !important;
}
}
pre [class~="redbox"] {
border: 2px solid var(--color-auto-red-5);
padding: 2px;
border-radius: 2px;
margin-right: 2px;
}
pre [class~="greenbox"] {
border: 2px solid var(--color-auto-green-5);
padding: 2px;
border-radius: 2px;
margin-right: 2px;
}
pre [class~="bluebox"] {
border: 2px solid var(--color-auto-blue-5);
padding: 2px;
border-radius: 2px;
margin-right: 2px;
}
}

View File

@@ -0,0 +1,31 @@
.markdownBody {
h1,
h2,
h3,
h4,
h5 {
padding-top: 16px;
}
h2 {
font-size: 1.25em;
}
// all h2 headers that are links should be blue-500
h2 a {
color: var(--color-auto-blue-5);
}
h3 {
font-size: 1em;
}
h4 {
font-size: 0.875em;
}
h5 {
font-size: 0.85em;
}
// needs specificity to override
[class~="lead-mktg"] p {
color: var(--color-auto-gray-9);
}
}

View File

@@ -0,0 +1,76 @@
.markdownBody {
ol {
counter-reset: li;
list-style: none;
position: relative;
padding-bottom: 10px;
padding-left: 0;
}
ol > li {
padding: 15px 0 15px 55px;
position: relative;
margin-bottom: 5px;
border-top: 3px solid var(--color-auto-gray-2);
}
ol > li:before {
content: counter(li);
counter-increment: li;
position: absolute;
top: 10px;
left: 0;
height: 100%;
width: 30px;
padding: 0 10px 0 0;
color: var(--color-auto-gray-4);
font-size: 22px;
font-weight: bold;
line-height: 35px;
text-align: right;
}
ol > li > p {
margin: 0;
}
ol > li > p:first-child {
margin-top: 0;
}
ol > li:after {
content: ".";
display: block;
clear: both;
visibility: hidden;
line-height: 0;
height: 0;
}
ol > li {
padding: 8px 0 8px 40px;
border: 0;
&:before {
top: 2px;
font-size: 16px;
width: 24px;
}
p:not(:first-child) {
margin-top: 15px;
}
[class~="extended-markdown"] {
margin-top: 15px;
}
}
ul ul,
ul ol,
ol ol,
ol ul {
margin-top: 15px;
margin-bottom: 15px;
}
}

View File

@@ -0,0 +1,82 @@
.markdownBody {
table {
display: table;
border-collapse: collapse;
position: relative;
font-size: 90%;
width: 100%;
line-height: 1.5;
/* We want to keep table-layout: auto so that column widths dynamically adjust;
otherwise entries get needlessly squashed into narrow columns. As a workaround,
we use components/lib/wrap-code-terms.js to prevent some reference table content
from expanding beyond the horizontal boundaries of the parent element. */
table-layout: auto;
code {
font-size: 85%;
padding: 0.2em 0.4em;
background-color: var(--color-markdown-code-bg);
border-radius: 6px;
}
pre > code {
padding: 0;
background-color: transparent;
}
thead tr {
border: none;
}
th {
font-weight: normal;
text-align: left;
position: sticky;
vertical-align: top;
z-index: 1;
top: 0;
background: var(--color-bg-primary);
box-shadow: 0 3px 0 0 var(--color-auto-gray-4);
padding: 12px 8px;
border: 0px;
}
th[align="center"] {
text-align: center;
}
th[align="right"] {
text-align: right;
}
th:first-child,
td:first-child {
padding-left: 0;
}
td {
padding: 10px 8px;
border: 0px;
vertical-align: top;
}
// markdown that has been converted to HTML is often wrapped in <p> tags
// don't let it interfere with the spacing
td p {
padding: 0;
margin: 0;
}
tr:nth-child(2n) {
background: none;
}
td.has-nested-table {
width: 100%;
table {
table-layout: auto;
}
}
}
}

View File

@@ -30,7 +30,7 @@ export default function parsePageSectionsIntoRecords(href, $) {
let records let records
const $sections = $('.markdown-body h2') const $sections = $('[data-search=article-content] h2')
.filter('[id]') .filter('[id]')
.filter((i, el) => { .filter((i, el) => {
return !ignoredHeadingSlugs.includes($(el).attr('id')) return !ignoredHeadingSlugs.includes($(el).attr('id'))
@@ -69,7 +69,7 @@ export default function parsePageSectionsIntoRecords(href, $) {
const objectID = href const objectID = href
const url = [urlPrefix, objectID].join('') const url = [urlPrefix, objectID].join('')
const content = $( const content = $(
'.article-grid-body p, .article-grid-body ul, .article-grid-body ol, .article-grid-body table' '[data-search=article-body] p, [data-search=article-body] ul, [data-search=article-body] ol, [data-search=article-body] table'
) )
.map((i, el) => $(el).text()) .map((i, el) => $(el).text())
.get() .get()

View File

@@ -1,13 +0,0 @@
/* Notes, tips, warning, and danger styles
------------------------------------------------------------------------------*/
.note,
.tip,
.warning,
.danger {
// remove extra space under lists inside of notes
ul,
ol {
margin-bottom: 0;
}
}

View File

@@ -1,52 +0,0 @@
/* Code style overrides
------------------------------------------------------------------------------*/
.markdown-body.playground pre {
padding: 0;
background-color: unset;
}
.markdown-body .highlight pre,
.markdown-body pre {
margin-top: 10px;
}
.height-constrained-code-block pre {
max-height: 500px;
overflow: auto;
}
.markdown-body .code-extra {
margin-top: $spacer-4;
pre {
margin-top: 0 !important;
border-top-left-radius: 0 !important;
border-top-right-radius: 0 !important;
border-left: 1px var(--color-auto-gray-2) solid !important;
border-bottom: 1px var(--color-auto-gray-2) solid !important;
border-right: 1px var(--color-auto-gray-2) solid !important;
}
}
/* code styles */
pre .redbox {
border: 2px solid var(--color-auto-red-5);
padding: 2px;
border-radius: 2px;
margin-right: 2px;
}
pre .greenbox {
border: 2px solid var(--color-auto-green-5);
padding: 2px;
border-radius: 2px;
margin-right: 2px;
}
pre .bluebox {
border: 2px solid var(--color-auto-blue-5);
padding: 2px;
border-radius: 2px;
margin-right: 2px;
}

View File

@@ -1,17 +1,30 @@
.extended-markdown p { .extended-markdown {
margin: 0; .note,
} .tip,
.warning,
.danger {
// remove extra space under lists inside of notes
ul,
ol {
margin-bottom: 0;
}
}
.extended-markdown p:not(:first-child) { p {
margin-top: 15px; margin: 0;
} }
.extended-markdown.note pre { p:not(:first-child) {
background: none; margin-top: 15px;
padding: 10px 10px 10px 0; }
margin-bottom: 0;
}
.extended-markdown.note pre code { &.note pre code {
color: var(--color-text-primary); color: var(--color-text-primary);
}
&.note pre {
background: none;
padding: 10px 10px 10px 0;
margin-bottom: 0;
}
} }

View File

@@ -1,6 +1,8 @@
// stylelint-disable primer/no-unused-vars // stylelint-disable primer/no-unused-vars
// Typography // Typography
@import "@primer/css/support/index.scss";
$marketing-font-path: "/assets/fonts/alliance/"; $marketing-font-path: "/assets/fonts/alliance/";
$font-family-mktg: "Alliance No.1", -apple-system, BlinkMacSystemFont, $font-family-mktg: "Alliance No.1", -apple-system, BlinkMacSystemFont,
"Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji",

View File

@@ -5,40 +5,3 @@ h3 {
color: var(--color-auto-gray-9); color: var(--color-auto-gray-9);
} }
} }
.markdown-body {
h1,
h2,
h3,
h4,
h5 {
font-family: $font-mktg;
font-weight: $font-weight-semibold;
padding-top: $spacer-3;
}
h2 {
font-size: 1.25em;
}
// all h2 headers that are links should be blue-500
h2 a {
color: var(--color-auto-blue-5);
}
#article-contents h2:not(.link-with-intro-title) {
padding-bottom: 0;
border-bottom: none;
}
h3 {
font-size: 1em;
}
h4 {
font-size: 0.875em;
}
h5 {
font-size: 0.85em;
}
}
// needs specificity to override
.markdown-body .lead-mktg p {
color: var(--color-auto-gray-9);
}

View File

@@ -9,16 +9,11 @@ $marketing-font-path: "/assets/fonts/inter/";
@import "@primer/css/marketing/index.scss"; @import "@primer/css/marketing/index.scss";
@import "font-mktg.scss"; @import "font-mktg.scss";
@import "alerts.scss";
@import "code.scss";
@import "extended-markdown.scss"; @import "extended-markdown.scss";
@import "font-mktg.scss"; @import "font-mktg.scss";
@import "gradient.scss"; @import "gradient.scss";
@import "headings.scss"; @import "headings.scss";
@import "images.scss"; @import "images.scss";
@import "lists.scss";
@import "shadows.scss"; @import "shadows.scss";
@import "summary.scss";
@import "syntax-highlighting.scss"; @import "syntax-highlighting.scss";
@import "tables.scss";
@import "utilities.scss"; @import "utilities.scss";

View File

@@ -1,77 +0,0 @@
/* Numbered procedures (step 1, step 2, ...)
------------------------------------------------------------------------------*/
.markdown-body ol {
counter-reset: li;
list-style: none;
position: relative;
padding-bottom: 10px;
padding-left: 0;
}
.markdown-body ol > li {
padding: 15px 0 15px 55px;
position: relative;
margin-bottom: 5px;
border-top: 3px solid var(--color-auto-gray-2);
}
.markdown-body ol > li:before {
content: counter(li);
counter-increment: li;
position: absolute;
top: 10px;
left: 0;
height: 100%;
width: 30px;
padding: 0 10px 0 0;
color: var(--color-auto-gray-4);
font-size: 22px;
font-weight: bold;
line-height: 35px;
text-align: right;
}
.markdown-body ol > li > p {
margin: 0;
}
.markdown-body ol > li > p:first-child {
margin-top: 0;
}
.markdown-body ol > li:after {
content: ".";
display: block;
clear: both;
visibility: hidden;
line-height: 0;
height: 0;
}
.markdown-body ol > li {
padding: $spacer-2 0 $spacer-2 $spacer-7;
border: 0;
&:before {
top: 2px;
font-size: $spacer-3;
width: $spacer-4;
}
p:not(:first-child) {
margin-top: 15px;
}
.extended-markdown {
margin-top: 15px;
}
}
.markdown-body ul ul,
.markdown-body ul ol,
.markdown-body ol ol,
.markdown-body ol ul {
margin-top: 15px;
margin-bottom: 15px;
}

View File

@@ -1,23 +0,0 @@
summary {
outline: none;
}
.markdown-body {
summary {
h1,
h2,
h3,
h4,
h5,
h6 {
display: inline-block;
margin-top: 10px;
margin-bottom: 10px;
p {
margin: 0;
padding: 0;
}
}
}
}

View File

@@ -1,91 +0,0 @@
// Largely overwritten in tables.scss
.markdown-body table {
display: table;
table-layout: fixed;
line-height: 1.5;
}
.markdown-body.playground table {
table-layout: fixed;
}
.markdown-body table {
border-collapse: collapse;
position: relative;
font-size: 90%;
width: 100%;
/* We want to keep table-layout: auto so that column widths dynamically adjust;
otherwise entries get needlessly squashed into narrow columns. As a workaround,
we use components/lib/wrap-code-terms.js to prevent some reference table content
from expanding beyond the horizontal boundaries of the parent element. */
table-layout: auto;
code {
font-size: 85%;
padding: 0.2em 0.4em;
background-color: rgba(0, 0, 0, 0.05);
border-radius: $border-radius;
}
pre {
> code {
padding: 0;
background-color: transparent;
}
}
thead tr {
border: none;
}
th {
font-weight: normal;
text-align: left;
position: sticky;
vertical-align: top;
z-index: 1;
top: 0;
background: var(--color-bg-primary);
box-shadow: 0 3px 0 0 var(--color-auto-gray-4);
padding: 12px 8px;
border: 0px;
}
th[align="center"] {
text-align: center;
}
th[align="right"] {
text-align: right;
}
th:first-child,
td:first-child {
padding-left: 0;
}
td {
padding: 10px 8px;
border: 0px;
vertical-align: top;
}
// markdown that has been converted to HTML is often wrapped in <p> tags
// don't let it interfere with the spacing
td p {
padding: 0;
margin: 0;
}
tr:nth-child(2n) {
background: none;
}
td.has-nested-table {
width: 100%;
table {
table-layout: auto;
}
}
}

View File

@@ -99,3 +99,7 @@
.fade-tertiary-bottom { .fade-tertiary-bottom {
background: linear-gradient(to top, var(--color-bg-tertiary), transparent); background: linear-gradient(to top, var(--color-bg-tertiary), transparent);
} }
.outline-none {
outline: none;
}

View File

@@ -1,7 +1,7 @@
<head> <head>
<meta name="keywords" content="topic1,topic2"> <meta name="keywords" content="topic1,topic2">
</head> </head>
<div class="markdown-body"> <div data-search="article-content">
<nav class="breadcrumbs"> <nav class="breadcrumbs">
<a href="#">GitHub Actions</a> <a href="#">GitHub Actions</a>
<a href="#">actions learning path</a> <a href="#">actions learning path</a>

View File

@@ -1,9 +1,9 @@
<head> <head>
<meta name="keywords" content="key1,key2,key3"> <meta name="keywords" content="key1,key2,key3" />
</head> </head>
<p>I am outside the article and should not be included</p> <p>I am outside the article and should not be included</p>
<div class="article-grid-body"> <div data-search="article-body">
<nav class="breadcrumbs"> <nav class="breadcrumbs">
<a href="#">Education</a> <a href="#">Education</a>
<a href="#">map topic</a> <a href="#">map topic</a>