From a3364a41cfe1fbfb6b555cd53aacc43feb2b9cd9 Mon Sep 17 00:00:00 2001 From: julieg18 Date: Wed, 30 Jun 2021 15:33:10 -0500 Subject: [PATCH] Add glossary page to doc/user-guide * add Documentation Markdown/Main and WithJSX components * add template for creating doc pages with jsx instead of markdown * add glossary page to pages directory --- content/docs/sidebar.json | 5 + .../Documentation/Markdown/Main/index.tsx | 109 ++++++ .../Markdown/Main/styles.module.css | 313 ++++++++++++++++++ .../Documentation/Markdown/index.tsx | 96 +----- .../Documentation/Markdown/styles.module.css | 312 ----------------- .../Documentation/WithJSX/index.tsx | 41 +++ src/components/Documentation/index.tsx | 5 +- src/gatsby/common.js | 2 + src/pages/doc/user-guide/glossary.tsx | 22 ++ src/templates/doc-jsx.tsx | 33 ++ 10 files changed, 534 insertions(+), 404 deletions(-) create mode 100644 src/components/Documentation/Markdown/Main/index.tsx create mode 100644 src/components/Documentation/Markdown/Main/styles.module.css create mode 100644 src/components/Documentation/WithJSX/index.tsx create mode 100644 src/pages/doc/user-guide/glossary.tsx create mode 100644 src/templates/doc-jsx.tsx diff --git a/content/docs/sidebar.json b/content/docs/sidebar.json index 834e686f5d1..0da54ce7d5e 100644 --- a/content/docs/sidebar.json +++ b/content/docs/sidebar.json @@ -94,6 +94,11 @@ "slug": "user-guide", "source": "user-guide/index.md", "children": [ + { + "label": "Glossary", + "slug": "glossary", + "source": "basic-concepts" + }, { "label": "What is DVC?", "slug": "what-is-dvc" diff --git a/src/components/Documentation/Markdown/Main/index.tsx b/src/components/Documentation/Markdown/Main/index.tsx new file mode 100644 index 00000000000..91a815f455c --- /dev/null +++ b/src/components/Documentation/Markdown/Main/index.tsx @@ -0,0 +1,109 @@ +import React, { useEffect, useRef, useCallback } from 'react' +import cn from 'classnames' +import { navigate } from '@reach/router' + +import Link from '../../../Link' +import Tutorials from '../../TutorialsLinks' +import { getPathWithSource } from '../../../../utils/shared/sidebar' + +import 'github-markdown-css/github-markdown.css' +import sharedStyles from '../../styles.module.css' +import styles from './styles.module.css' + +const isInsideCodeBlock = (node: Element): boolean => { + while (node?.parentNode) { + if (node.tagName === 'PRE') { + return true + } + + if (node.tagName === 'ARTICLE') { + return false + } + + node = node.parentNode as Element + } + + return false +} + +interface IMainProps { + githubLink: string + tutorials: { [type: string]: string } + prev?: string + next?: string +} + +const Main: React.FC = ({ + children, + prev, + next, + tutorials, + githubLink +}) => { + const touchstartXRef = useRef(0) + const touchendXRef = useRef(0) + const isCodeBlockRef = useRef(false) + const handleSwipeGesture = useCallback(() => { + if (isCodeBlockRef.current) return + + if (next && touchstartXRef.current - touchendXRef.current > 100) { + navigate(next) + } + + if (prev && touchendXRef.current - touchstartXRef.current > 100) { + navigate(prev) + } + }, [prev, next]) + const onTouchStart = useCallback(e => { + isCodeBlockRef.current = isInsideCodeBlock(e.target) + touchstartXRef.current = e.changedTouches[0].screenX + }, []) + const onTouchEnd = useCallback(e => { + touchendXRef.current = e.changedTouches[0].screenX + handleSwipeGesture() + }, []) + + useEffect(() => { + document.addEventListener('touchstart', onTouchStart, false) + document.addEventListener('touchend', onTouchEnd, false) + + return (): void => { + document.removeEventListener('touchstart', onTouchStart) + document.removeEventListener('touchend', onTouchEnd) + } + }, []) + + return ( +
+ {tutorials && ( +
+ +
+ )} + + Edit on + GitHub + +
{children}
+
+ + + Prev + + + Next + + +
+
+ ) +} + +export default Main diff --git a/src/components/Documentation/Markdown/Main/styles.module.css b/src/components/Documentation/Markdown/Main/styles.module.css new file mode 100644 index 00000000000..89c2141166f --- /dev/null +++ b/src/components/Documentation/Markdown/Main/styles.module.css @@ -0,0 +1,313 @@ +:global { + ul { + list-style-type: disc; + } + + ol { + list-style-type: decimal; + } + + em { + font-style: italic; + } + + #markdown-root { + @keyframes fadeIn { + from { + opacity: 0; + } + + to { + opacity: 1; + } + } + + animation-duration: 1s; + animation-fill-mode: both; + + :local { + animation-name: fadeIn; + } + } + + .markdown-body { + font-family: inherit; + font-size: 18px; + + h1, + h2, + h3, + h4, + h5, + h6 { + font-weight: 500; + } + + img + em, + :global(.gatsby-resp-image-wrapper) + em { + color: #6a737d; + font-size: 0.9em; + display: block; + margin-top: -6px; + text-align: center; + } + + :global(.gatsby-resp-image-wrapper) + em { + margin-top: 0; + } + + a[target='_blank'] { + white-space: nowrap; + + &::after { + position: relative; + top: 1px; + right: 0; + width: 12px; + height: 12px; + margin-left: 1px; + content: url(/img/external-link.svg); + } + } + + :global(a.gatsby-resp-image-link)::after { + content: unset; + } + + .anchor { + margin-left: -24px; + } + + li { + margin: 16px 0; + } + + pre[class*='language-'] { + background: #40354d; + color: #ccc; + + .token.line { + color: #ddd; + } + + .token.comment, + .token.block-comment { + font-weight: normal; + color: #a0a0a0; + } + + .token.input { + user-select: none; + } + + .token.prolog, + .token.doctype, + .token.cdata { + color: #999; + } + + .token.url, + .token.constant, + .token.operator, + .token.punctuation { + color: #a0a0a0; + } + + .token.property, + .token.tag, + .token.boolean, + .token.function-name, + .token.symbol, + .token.deleted { + color: #4badd2; + } + + .token.function { + color: #ae41bb; + } + + .token.number, + .token.attr-name, + .token.string, + .token.char, + .token.builtin, + .token.inserted { + color: #219161; + } + + .token.entity, + .token.variable { + color: #a67f59; + } + + .token.class-name { + color: #0086b3; + } + + .token.dvc { + color: #56b1d0; + font-weight: bold; + } + + .token.usage, + .token.git { + color: #e9836e; + } + + .token.command, + .token.selector, + .token.atrule, + .token.attr-value, + .token.keyword { + color: #e4b872; + } + + .token.regex, + .token.important { + color: #b68; + } + + .token.parameter { + color: #a0a0a0; + } + + .token.function-variable { + color: #7ece42; + } + + .token.important { + font-weight: normal; + } + + .token.bold { + font-weight: bold; + } + + .token.italic { + font-style: italic; + } + + .token.entity { + cursor: help; + } + + .token.namespace { + opacity: 0.7; + } + } + } + + details p { + font-size: 17px; + color: var(--color-gray-dark); + margin-left: 20px; + margin-right: 10px; + } + + details pre { + font-size: 14px; + color: var(--color-gray-dark); + margin-left: 20px; + margin-right: 10px; + } +} + +.content { + min-width: 200px; + margin: 30px; + flex: 1; + background-color: #fff; + + @media (--xs-scr) { + margin: 15px 0; + } +} + +.tutorialsWrapper { + position: relative; + z-index: 1; + float: right; + margin: 5px 0 0 10px; + + @media (--md-scr) { + margin: 0 0 15px 0; + } + + @media only screen and (min-width: 1200px) { + display: none; + } +} + +.githubLink { + display: none; + float: right; + margin: 5px 0 10px 10px; + z-index: 1; + position: relative; + + @media (--md-scr) { + float: none; + margin: 0 0 15px 0; + } + + @media only screen and (max-width: 1200px) { + display: inline-flex; + } +} + +.githubIcon { + background-image: url(/img/github_icon.svg); +} + +.navButtons { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: 40px; + font-size: 14px; + font-weight: 600; +} + +.navButton { + text-decoration: none; + background: white; + padding: 10px 15px; + text-transform: uppercase; + color: #333; + border-bottom: 3px solid #13adc7; + display: inline-flex; + align-items: center; + transition: 0.2s border-color ease-out; + + &:hover { + border-bottom: 3px solid #11849b; + } + + &[disabled] { + pointer-events: none; + opacity: 0.5; + } +} + +.navButtonIcon { + display: inline-block; + width: 1em; + height: 1em; + line-height: 1; + background-image: url(/img/arrow.svg); + background-size: contain; + background-position: center; + background-repeat: no-repeat; + transition: all 0.3s; + + &.next { + margin-left: 7px; + } + + &.prev { + margin-right: 7px; + mask-position: center; + transform: rotate(180deg); + margin-top: 2px; + } +} diff --git a/src/components/Documentation/Markdown/index.tsx b/src/components/Documentation/Markdown/index.tsx index 625c35c1697..fc76f76243b 100644 --- a/src/components/Documentation/Markdown/index.tsx +++ b/src/components/Documentation/Markdown/index.tsx @@ -1,40 +1,13 @@ -import React, { - useCallback, - useEffect, - useRef, - ReactNode, - ReactElement -} from 'react' -import cn from 'classnames' -import { navigate } from '@reach/router' +import React, { ReactNode, ReactElement } from 'react' import rehypeReact from 'rehype-react' import Collapsible from 'react-collapsible' +import Main from './Main' import Link from '../../Link' import Tooltip from './Tooltip' -import Tutorials from '../TutorialsLinks' -import { getPathWithSource } from '../../../utils/shared/sidebar' -import 'github-markdown-css/github-markdown.css' -import sharedStyles from '../styles.module.css' import styles from './styles.module.css' -const isInsideCodeBlock = (node: Element): boolean => { - while (node?.parentNode) { - if (node.tagName === 'PRE') { - return true - } - - if (node.tagName === 'ARTICLE') { - return false - } - - node = node.parentNode as Element - } - - return false -} - const Details: React.FC<{ children: Array<{ props: { children: ReactNode } } | string> }> = ({ children }) => { @@ -150,69 +123,10 @@ const Markdown: React.FC = ({ tutorials, githubLink }) => { - const touchstartXRef = useRef(0) - const touchendXRef = useRef(0) - const isCodeBlockRef = useRef(false) - const handleSwipeGesture = useCallback(() => { - if (isCodeBlockRef.current) return - - if (next && touchstartXRef.current - touchendXRef.current > 100) { - navigate(next) - } - - if (prev && touchendXRef.current - touchstartXRef.current > 100) { - navigate(prev) - } - }, [prev, next]) - const onTouchStart = useCallback(e => { - isCodeBlockRef.current = isInsideCodeBlock(e.target) - touchstartXRef.current = e.changedTouches[0].screenX - }, []) - const onTouchEnd = useCallback(e => { - touchendXRef.current = e.changedTouches[0].screenX - handleSwipeGesture() - }, []) - - useEffect(() => { - document.addEventListener('touchstart', onTouchStart, false) - document.addEventListener('touchend', onTouchEnd, false) - - return (): void => { - document.removeEventListener('touchstart', onTouchStart) - document.removeEventListener('touchend', onTouchEnd) - } - }, []) - return ( -
- {tutorials && ( -
- -
- )} - - Edit on - GitHub - -
{renderAst(htmlAst)}
-
- - - Prev - - - Next - - -
-
+
+ {renderAst(htmlAst)} +
) } diff --git a/src/components/Documentation/Markdown/styles.module.css b/src/components/Documentation/Markdown/styles.module.css index 7b80e711c5c..08f999dfb36 100644 --- a/src/components/Documentation/Markdown/styles.module.css +++ b/src/components/Documentation/Markdown/styles.module.css @@ -1,202 +1,4 @@ :global { - ul { - list-style-type: disc; - } - - ol { - list-style-type: decimal; - } - - em { - font-style: italic; - } - - #markdown-root { - @keyframes fadeIn { - from { - opacity: 0; - } - - to { - opacity: 1; - } - } - - animation-duration: 1s; - animation-fill-mode: both; - - :local { - animation-name: fadeIn; - } - } - - .markdown-body { - font-family: inherit; - font-size: 18px; - - h1, - h2, - h3, - h4, - h5, - h6 { - font-weight: 500; - } - - img + em, - :global(.gatsby-resp-image-wrapper) + em { - color: #6a737d; - font-size: 0.9em; - display: block; - margin-top: -6px; - text-align: center; - } - - :global(.gatsby-resp-image-wrapper) + em { - margin-top: 0; - } - - a[target='_blank'] { - white-space: nowrap; - - &::after { - position: relative; - top: 1px; - right: 0; - width: 12px; - height: 12px; - margin-left: 1px; - content: url(/img/external-link.svg); - } - } - - :global(a.gatsby-resp-image-link)::after { - content: unset; - } - - .anchor { - margin-left: -24px; - } - - li { - margin: 16px 0; - } - - pre[class*='language-'] { - background: #40354d; - color: #ccc; - - .token.line { - color: #ddd; - } - - .token.comment, - .token.block-comment { - font-weight: normal; - color: #a0a0a0; - } - - .token.input { - user-select: none; - } - - .token.prolog, - .token.doctype, - .token.cdata { - color: #999; - } - - .token.url, - .token.constant, - .token.operator, - .token.punctuation { - color: #a0a0a0; - } - - .token.property, - .token.tag, - .token.boolean, - .token.function-name, - .token.symbol, - .token.deleted { - color: #4badd2; - } - - .token.function { - color: #ae41bb; - } - - .token.number, - .token.attr-name, - .token.string, - .token.char, - .token.builtin, - .token.inserted { - color: #219161; - } - - .token.entity, - .token.variable { - color: #a67f59; - } - - .token.class-name { - color: #0086b3; - } - - .token.dvc { - color: #56b1d0; - font-weight: bold; - } - - .token.usage, - .token.git { - color: #e9836e; - } - - .token.command, - .token.selector, - .token.atrule, - .token.attr-value, - .token.keyword { - color: #e4b872; - } - - .token.regex, - .token.important { - color: #b68; - } - - .token.parameter { - color: #a0a0a0; - } - - .token.function-variable { - color: #7ece42; - } - - .token.important { - font-weight: normal; - } - - .token.bold { - font-weight: bold; - } - - .token.italic { - font-style: italic; - } - - .token.entity { - cursor: help; - } - - .token.namespace { - opacity: 0.7; - } - } - } - .Collapsible { margin-bottom: 10px; background-color: rgba(36, 173, 197, 0.2); @@ -237,120 +39,6 @@ -moz-border-radius: 15px; padding: 10px; } - - details p { - font-size: 17px; - color: var(--color-gray-dark); - margin-left: 20px; - margin-right: 10px; - } - - details pre { - font-size: 14px; - color: var(--color-gray-dark); - margin-left: 20px; - margin-right: 10px; - } -} - -.content { - min-width: 200px; - margin: 30px; - flex: 1; - background-color: #fff; - - @media (--xs-scr) { - margin: 15px 0; - } -} - -.tutorialsWrapper { - position: relative; - z-index: 1; - float: right; - margin: 5px 0 0 10px; - - @media (--md-scr) { - margin: 0 0 15px 0; - } - - @media only screen and (min-width: 1200px) { - display: none; - } -} - -.githubLink { - display: none; - float: right; - margin: 5px 0 10px 10px; - z-index: 1; - position: relative; - - @media (--md-scr) { - float: none; - margin: 0 0 15px 0; - } - - @media only screen and (max-width: 1200px) { - display: inline-flex; - } -} - -.githubIcon { - background-image: url(/img/github_icon.svg); -} - -.navButtons { - display: flex; - justify-content: space-between; - align-items: center; - margin-top: 40px; - font-size: 14px; - font-weight: 600; -} - -.navButton { - text-decoration: none; - background: white; - padding: 10px 15px; - text-transform: uppercase; - color: #333; - border-bottom: 3px solid #13adc7; - display: inline-flex; - align-items: center; - transition: 0.2s border-color ease-out; - - &:hover { - border-bottom: 3px solid #11849b; - } - - &[disabled] { - pointer-events: none; - opacity: 0.5; - } -} - -.navButtonIcon { - display: inline-block; - width: 1em; - height: 1em; - line-height: 1; - background-image: url(/img/arrow.svg); - background-size: contain; - background-position: center; - background-repeat: no-repeat; - transition: all 0.3s; - - &.next { - margin-left: 7px; - } - - &.prev { - margin-right: 7px; - mask-position: center; - transform: rotate(180deg); - margin-top: 2px; - } } .cards { diff --git a/src/components/Documentation/WithJSX/index.tsx b/src/components/Documentation/WithJSX/index.tsx new file mode 100644 index 00000000000..78747fc4352 --- /dev/null +++ b/src/components/Documentation/WithJSX/index.tsx @@ -0,0 +1,41 @@ +import React from 'react' + +import MarkdownMain from '../Markdown/Main' +import RightPanel from '../RightPanel' + +import { IHeading, getGithubLink } from '../' +import { getItemByPath } from '../../../utils/shared/sidebar' + +interface IDocumentationProps { + path: string + headings: Array +} + +const Documentation: React.FC = ({ + children, + path, + headings +}) => { + const { source, prev, next, tutorials } = getItemByPath(path) + const githubLink = getGithubLink(source) + + return ( + <> + + {children} + + + + ) +} + +export default Documentation diff --git a/src/components/Documentation/index.tsx b/src/components/Documentation/index.tsx index 64b7618cd82..88c2cf480fb 100644 --- a/src/components/Documentation/index.tsx +++ b/src/components/Documentation/index.tsx @@ -10,6 +10,9 @@ export interface IHeading { text: string } +export const getGithubLink = (source: string): string => + `https://github.com/iterative/dvc.org/blob/master/content${source}` + interface IDocumentationProps { path: string headings: Array @@ -22,7 +25,7 @@ const Documentation: React.FC = ({ headings }) => { const { source, prev, next, tutorials } = getItemByPath(path) - const githubLink = `https://github.com/iterative/dvc.org/blob/master/content${source}` + const githubLink = getGithubLink(source) return ( <> diff --git a/src/gatsby/common.js b/src/gatsby/common.js index ccbf661c684..21960a1d899 100644 --- a/src/gatsby/common.js +++ b/src/gatsby/common.js @@ -1,6 +1,7 @@ const remark = require('remark') const remarkHTML = require('remark-html') const is404Regexp = /^\/404/ +const isDocsRegexp = /^\/doc/ const trailingSlashRegexp = /\/$/ const alertLandingArray = ['/enterprise'] @@ -25,6 +26,7 @@ const setPageContext = (page, actions) => { context: { ...page.context, is404: is404Regexp.test(page.path), + isDocs: isDocsRegexp.test(page.path), isAlertLanding } }) diff --git a/src/pages/doc/user-guide/glossary.tsx b/src/pages/doc/user-guide/glossary.tsx new file mode 100644 index 00000000000..4f255d8593a --- /dev/null +++ b/src/pages/doc/user-guide/glossary.tsx @@ -0,0 +1,22 @@ +import React from 'react' + +import DocWithJsx from '../../../templates/doc-jsx' +import useGlossary from '../../../utils/front/glossary' + +const Glossary: React.FC = () => { + const { contents } = useGlossary() + + return ( + +

Glossary

+ {contents + .sort((c1, c2) => (c1.name < c2.name ? -1 : c1.name < c2.name ? 1 : 0)) + .map(({ name, desc }: { name: string; desc: string }, i: number) => { + const html = `${name}: ${desc.replace(//, '')}` + return

+ })} + + ) +} + +export default Glossary diff --git a/src/templates/doc-jsx.tsx b/src/templates/doc-jsx.tsx new file mode 100644 index 00000000000..94f85676da6 --- /dev/null +++ b/src/templates/doc-jsx.tsx @@ -0,0 +1,33 @@ +import React from 'react' +import { getItemByPath } from '../utils/shared/sidebar' + +import SEO from '../components/SEO' + +import Documentation from '../components/Documentation/WithJSX' + +export interface IJSXDocPageProps { + title?: string + description?: string + slug: string + headings: [] +} + +const JSXDocPage: React.FC = ({ + title, + description, + children, + slug, + headings +}) => { + const { label } = getItemByPath(slug) + return ( + <> + + + {children} + + + ) +} + +export default JSXDocPage