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:
@@ -1,15 +1,14 @@
|
||||
import React, { ReactNode, ReactHTML } from 'react'
|
||||
import React, { ReactNode } from 'react'
|
||||
import cx from 'classnames'
|
||||
|
||||
type Props = {
|
||||
as?: keyof ReactHTML
|
||||
as?: keyof JSX.IntrinsicElements
|
||||
maxLines: number
|
||||
children: ReactNode
|
||||
className?: string
|
||||
}
|
||||
export const TruncateLines = (props: Props) => {
|
||||
const { as, maxLines, className, children } = props
|
||||
const Component = as || 'div'
|
||||
const { maxLines, className, children, as: Component = 'div' } = props
|
||||
return (
|
||||
<Component className={cx('root', className)}>
|
||||
{children}
|
||||
|
||||
@@ -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 }}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -22,12 +22,9 @@ export const ArticleGridLayout = ({ head, toc, children, className }: Props) =>
|
||||
)}
|
||||
|
||||
{/* content */}
|
||||
{/*
|
||||
NOTE: The article-grid-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.
|
||||
*/}
|
||||
<div className={cx(styles.content, 'article-grid-body')}>{children}</div>
|
||||
<div data-search="article-body" className={styles.content}>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import { ArticleTitle } from 'components/article/ArticleTitle'
|
||||
import { useArticleContext } from 'components/context/ArticleContext'
|
||||
import { useTranslation } from 'components/hooks/useTranslation'
|
||||
import { LearningTrackNav } from './LearningTrackNav'
|
||||
import { ArticleContent } from './ArticleContent'
|
||||
import { MarkdownContent } from 'components/ui/MarkdownContent'
|
||||
import { ArticleGridLayout } from './ArticleGridLayout'
|
||||
|
||||
// Mapping of a "normal" article to it's interactive counterpart
|
||||
@@ -63,12 +63,7 @@ export const ArticlePage = () => {
|
||||
</Callout>
|
||||
)}
|
||||
|
||||
{intro && (
|
||||
<div
|
||||
className="lead-mktg markdown-body mb-3"
|
||||
dangerouslySetInnerHTML={{ __html: intro }}
|
||||
/>
|
||||
)}
|
||||
{intro && <MarkdownContent className="lead-mktg mb-3">{intro}</MarkdownContent>}
|
||||
|
||||
{permissions && (
|
||||
<div
|
||||
@@ -153,7 +148,9 @@ export const ArticlePage = () => {
|
||||
</>
|
||||
}
|
||||
>
|
||||
<ArticleContent>{renderedPage}</ArticleContent>
|
||||
<div id="article-contents">
|
||||
<MarkdownContent>{renderedPage}</MarkdownContent>
|
||||
</div>
|
||||
</ArticleGridLayout>
|
||||
|
||||
{currentLearningTrack?.trackName ? (
|
||||
|
||||
@@ -25,7 +25,7 @@ export const ArticleVersionPicker = () => {
|
||||
`}
|
||||
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>{' '}
|
||||
{allVersions[currentVersion].versionTitle}
|
||||
<Dropdown.Caret />
|
||||
|
||||
@@ -25,7 +25,7 @@ export const HomepageVersionPicker = ({ variant }: Props) => {
|
||||
if (variant === 'inline') {
|
||||
return (
|
||||
<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">
|
||||
<span>{label}</span>
|
||||
<ChevronDownIcon size={24} className="arrow ml-md-1" />
|
||||
|
||||
@@ -3,7 +3,7 @@ import { TableOfContents } from 'components/landing/TableOfContents'
|
||||
import { useTocLandingContext } from 'components/context/TocLandingContext'
|
||||
import { ArticleTopper } from 'components/article/ArticleTopper'
|
||||
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 { useTranslation } from 'components/hooks/useTranslation'
|
||||
import { ArticleGridLayout } from 'components/article/ArticleGridLayout'
|
||||
@@ -55,7 +55,11 @@ export const TocLanding = () => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{renderedPage && <ArticleContent>{renderedPage}</ArticleContent>}
|
||||
{renderedPage && (
|
||||
<div id="article-contents">
|
||||
<MarkdownContent>{renderedPage}</MarkdownContent>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<TableOfContents items={tocItems} variant={variant} />
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,7 @@ import parseUserAgent from './user-agent'
|
||||
import { sendEvent, EventType } from './events'
|
||||
|
||||
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)
|
||||
|
||||
@@ -66,9 +66,7 @@ function setActiveSwitcherLinks(platform: string) {
|
||||
function showPlatformSpecificContent(platform: string) {
|
||||
// find all platform-specific *block* elements and hide or show as appropriate
|
||||
// example: {{ #mac }} block content {{/mac}}
|
||||
const markdowns = Array.from(
|
||||
document.querySelectorAll('.extended-markdown')
|
||||
) as Array<HTMLElement>
|
||||
const markdowns = Array.from(document.querySelectorAll<HTMLElement>('.extended-markdown'))
|
||||
markdowns
|
||||
.filter((el) => supportedPlatforms.some((platform) => el.classList.contains(platform)))
|
||||
.forEach((el) => {
|
||||
@@ -78,8 +76,8 @@ function showPlatformSpecificContent(platform: string) {
|
||||
// find all platform-specific *inline* elements and hide or show as appropriate
|
||||
// example: <span class="platform-mac">inline content</span>
|
||||
const platforms = Array.from(
|
||||
document.querySelectorAll('.platform-mac, .platform-windows, .platform-linux')
|
||||
) as Array<HTMLElement>
|
||||
document.querySelectorAll<HTMLElement>('.platform-mac, .platform-windows, .platform-linux')
|
||||
)
|
||||
platforms.forEach((el) => {
|
||||
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
|
||||
// example: <span class="platform-mac">inline content</span>
|
||||
const platformEls = Array.from(
|
||||
document.querySelectorAll('.platform-mac, .platform-windows, .platform-linux')
|
||||
) as Array<HTMLElement>
|
||||
document.querySelectorAll<HTMLElement>('.platform-mac, .platform-windows, .platform-linux')
|
||||
)
|
||||
platformEls.forEach((el) => detectPlatforms(el))
|
||||
|
||||
return Array.from(detectedPlatforms) as Array<string>
|
||||
return Array.from(detectedPlatforms)
|
||||
}
|
||||
|
||||
function detectPlatforms(el: HTMLElement) {
|
||||
|
||||
@@ -20,7 +20,7 @@ export const LanguagePicker = ({ variant }: Props) => {
|
||||
if (variant === 'inline') {
|
||||
return (
|
||||
<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">
|
||||
<span>{selectedLang.nativeName || selectedLang.name}</span>
|
||||
<ChevronDownIcon size={24} className="arrow ml-md-1" />
|
||||
|
||||
@@ -13,7 +13,11 @@ export const ProductPicker = () => {
|
||||
|
||||
return (
|
||||
<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">
|
||||
{/* <!-- 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 --> */}
|
||||
|
||||
10
components/playground/ArticleMarkdown.module.scss
Normal file
10
components/playground/ArticleMarkdown.module.scss
Normal file
@@ -0,0 +1,10 @@
|
||||
.articleMarkdown {
|
||||
pre {
|
||||
padding: 0;
|
||||
background-color: unset;
|
||||
}
|
||||
|
||||
table {
|
||||
table-layout: fixed !important;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,15 @@
|
||||
import React from 'react'
|
||||
import cx from 'classnames'
|
||||
import { useTheme } from '@primer/components'
|
||||
import ReactMarkdown from 'react-markdown'
|
||||
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
|
||||
import { vs, vscDarkPlus } from 'react-syntax-highlighter/dist/cjs/styles/prism'
|
||||
import gfm from 'remark-gfm'
|
||||
|
||||
import { MarkdownContent } from 'components/ui/MarkdownContent'
|
||||
|
||||
import styles from './ArticleMarkdown.module.scss'
|
||||
|
||||
type Props = {
|
||||
className?: string
|
||||
children: string
|
||||
@@ -13,8 +18,9 @@ export const ArticleMarkdown = ({ className, children }: Props) => {
|
||||
const theme = useTheme()
|
||||
|
||||
return (
|
||||
<MarkdownContent>
|
||||
<ReactMarkdown
|
||||
className={className}
|
||||
className={cx(styles.articleMarkdown, className)}
|
||||
remarkPlugins={[gfm as any]}
|
||||
components={{
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
@@ -38,5 +44,6 @@ export const ArticleMarkdown = ({ className, children }: Props) => {
|
||||
>
|
||||
{children}
|
||||
</ReactMarkdown>
|
||||
</MarkdownContent>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import cx from 'classnames'
|
||||
import { ChevronDownIcon } from '@primer/octicons-react'
|
||||
import { GHAEReleaseNotePatch } from './GHAEReleaseNotePatch'
|
||||
import { GHAEReleaseNotesContextT } from './types'
|
||||
import { MarkdownContent } from 'components/ui/MarkdownContent'
|
||||
|
||||
type GitHubAEProps = {
|
||||
context: GHAEReleaseNotesContextT
|
||||
@@ -20,7 +21,7 @@ export function GHAEReleaseNotes({ context }: GitHubAEProps) {
|
||||
<div></div>
|
||||
</div>
|
||||
|
||||
<div className="markdown-body">
|
||||
<MarkdownContent data-search="article-content">
|
||||
{releaseNotes.map((patch) => {
|
||||
return (
|
||||
<GHAEReleaseNotePatch
|
||||
@@ -30,14 +31,15 @@ export function GHAEReleaseNotes({ context }: GitHubAEProps) {
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</MarkdownContent>
|
||||
</article>
|
||||
|
||||
<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' }}
|
||||
>
|
||||
<nav className="height-full overflow-auto">
|
||||
<MarkdownContent data-search="article-content">
|
||||
<ul className="list-style-none pl-0 text-bold">
|
||||
{releases.map((release) => {
|
||||
return (
|
||||
@@ -49,6 +51,7 @@ export function GHAEReleaseNotes({ context }: GitHubAEProps) {
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
</MarkdownContent>
|
||||
</nav>
|
||||
</aside>
|
||||
</div>
|
||||
@@ -78,7 +81,7 @@ const CollapsibleReleaseSection = ({
|
||||
open={defaultIsOpen}
|
||||
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}
|
||||
<div className="d-flex">
|
||||
<span className="color-text-tertiary text-mono text-small text-normal mr-1">
|
||||
|
||||
@@ -10,6 +10,7 @@ import { useMainContext } from 'components/context/MainContext'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
import { Link } from 'components/Link'
|
||||
import { MarkdownContent } from 'components/ui/MarkdownContent'
|
||||
import { GHESReleaseNotesContextT } from './types'
|
||||
import { GHESReleaseNotePatch } from './GHESReleaseNotePatch'
|
||||
|
||||
@@ -59,7 +60,7 @@ export function GHESReleaseNotes({ context }: Props) {
|
||||
<div />
|
||||
)}
|
||||
</div>
|
||||
<div className="markdown-body">
|
||||
<MarkdownContent data-search="article-content">
|
||||
{releaseNotes.map((patch) => {
|
||||
return (
|
||||
<GHESReleaseNotePatch
|
||||
@@ -75,14 +76,15 @@ export function GHESReleaseNotes({ context }: Props) {
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</MarkdownContent>
|
||||
</article>
|
||||
|
||||
<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' }}
|
||||
>
|
||||
<nav className="height-full overflow-auto">
|
||||
<MarkdownContent data-search="article-content">
|
||||
<ul className="list-style-none pl-0 text-bold">
|
||||
{releases.map((release) => {
|
||||
const releaseLink = `/${currentLanguage}/${currentVersion.plan}@${release.version}/${currentProduct?.id}/release-notes`
|
||||
@@ -127,6 +129,7 @@ export function GHESReleaseNotes({ context }: Props) {
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
</MarkdownContent>
|
||||
</nav>
|
||||
</aside>
|
||||
</div>
|
||||
@@ -157,7 +160,7 @@ const CollapsibleReleaseSection = ({
|
||||
open={defaultIsOpen}
|
||||
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}
|
||||
<div className="d-flex">
|
||||
<span className="color-text-tertiary text-mono text-small text-normal mr-1">
|
||||
|
||||
@@ -140,7 +140,7 @@ const CollapsibleSection = (props: SectionProps) => {
|
||||
|
||||
return (
|
||||
<details open={defaultOpen} onToggle={onToggle} className="details-reset">
|
||||
<summary>
|
||||
<summary className="outline-none">
|
||||
<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">
|
||||
{title}
|
||||
|
||||
37
components/ui/MarkdownContent/MarkdownContent.module.scss
Normal file
37
components/ui/MarkdownContent/MarkdownContent.module.scss
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
26
components/ui/MarkdownContent/MarkdownContent.tsx
Normal file
26
components/ui/MarkdownContent/MarkdownContent.tsx
Normal 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 })}
|
||||
/>
|
||||
)
|
||||
}
|
||||
1
components/ui/MarkdownContent/index.ts
Normal file
1
components/ui/MarkdownContent/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { MarkdownContent } from './MarkdownContent'
|
||||
45
components/ui/MarkdownContent/stylesheets/code.scss
Normal file
45
components/ui/MarkdownContent/stylesheets/code.scss
Normal 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;
|
||||
}
|
||||
}
|
||||
31
components/ui/MarkdownContent/stylesheets/headers.scss
Normal file
31
components/ui/MarkdownContent/stylesheets/headers.scss
Normal 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);
|
||||
}
|
||||
}
|
||||
76
components/ui/MarkdownContent/stylesheets/lists.scss
Normal file
76
components/ui/MarkdownContent/stylesheets/lists.scss
Normal 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;
|
||||
}
|
||||
}
|
||||
82
components/ui/MarkdownContent/stylesheets/table.scss
Normal file
82
components/ui/MarkdownContent/stylesheets/table.scss
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ export default function parsePageSectionsIntoRecords(href, $) {
|
||||
|
||||
let records
|
||||
|
||||
const $sections = $('.markdown-body h2')
|
||||
const $sections = $('[data-search=article-content] h2')
|
||||
.filter('[id]')
|
||||
.filter((i, el) => {
|
||||
return !ignoredHeadingSlugs.includes($(el).attr('id'))
|
||||
@@ -69,7 +69,7 @@ export default function parsePageSectionsIntoRecords(href, $) {
|
||||
const objectID = href
|
||||
const url = [urlPrefix, objectID].join('')
|
||||
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())
|
||||
.get()
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1,17 +1,30 @@
|
||||
.extended-markdown p {
|
||||
.extended-markdown {
|
||||
.note,
|
||||
.tip,
|
||||
.warning,
|
||||
.danger {
|
||||
// remove extra space under lists inside of notes
|
||||
ul,
|
||||
ol {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.extended-markdown p:not(:first-child) {
|
||||
p:not(:first-child) {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.extended-markdown.note pre {
|
||||
&.note pre code {
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
&.note pre {
|
||||
background: none;
|
||||
padding: 10px 10px 10px 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.extended-markdown.note pre code {
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// stylelint-disable primer/no-unused-vars
|
||||
// Typography
|
||||
|
||||
@import "@primer/css/support/index.scss";
|
||||
|
||||
$marketing-font-path: "/assets/fonts/alliance/";
|
||||
$font-family-mktg: "Alliance No.1", -apple-system, BlinkMacSystemFont,
|
||||
"Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji",
|
||||
|
||||
@@ -5,40 +5,3 @@ h3 {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -9,16 +9,11 @@ $marketing-font-path: "/assets/fonts/inter/";
|
||||
@import "@primer/css/marketing/index.scss";
|
||||
@import "font-mktg.scss";
|
||||
|
||||
@import "alerts.scss";
|
||||
@import "code.scss";
|
||||
@import "extended-markdown.scss";
|
||||
@import "font-mktg.scss";
|
||||
@import "gradient.scss";
|
||||
@import "headings.scss";
|
||||
@import "images.scss";
|
||||
@import "lists.scss";
|
||||
@import "shadows.scss";
|
||||
@import "summary.scss";
|
||||
@import "syntax-highlighting.scss";
|
||||
@import "tables.scss";
|
||||
@import "utilities.scss";
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,3 +99,7 @@
|
||||
.fade-tertiary-bottom {
|
||||
background: linear-gradient(to top, var(--color-bg-tertiary), transparent);
|
||||
}
|
||||
|
||||
.outline-none {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<head>
|
||||
<meta name="keywords" content="topic1,topic2">
|
||||
</head>
|
||||
<div class="markdown-body">
|
||||
<div data-search="article-content">
|
||||
<nav class="breadcrumbs">
|
||||
<a href="#">GitHub Actions</a>
|
||||
<a href="#">actions learning path</a>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<head>
|
||||
<meta name="keywords" content="key1,key2,key3">
|
||||
<meta name="keywords" content="key1,key2,key3" />
|
||||
</head>
|
||||
<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">
|
||||
<a href="#">Education</a>
|
||||
<a href="#">map topic</a>
|
||||
|
||||
Reference in New Issue
Block a user