Skip to content

Commit

Permalink
DOP-4615: (Feature) New Structured Data (#1274)
Browse files Browse the repository at this point in the history
Co-authored-by: Seung Park <[email protected]>
  • Loading branch information
rayangler and seungpark authored Oct 8, 2024
1 parent 6f3b77b commit 5c07775
Show file tree
Hide file tree
Showing 29 changed files with 1,979 additions and 202 deletions.
2 changes: 2 additions & 0 deletions plugins/gatsby-source-snooty-prod/gatsby-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ exports.sourceNodes = async ({ actions, createContentDigest, createNodeId, getNo
id: key,
page_id: key,
ast: doc.ast,
facets: doc.facets,
internal: {
type: 'Page',
contentDigest: createContentDigest(doc),
Expand Down Expand Up @@ -379,6 +380,7 @@ exports.createSchemaCustomization = ({ actions }) => {
branch: String
pagePath: String
ast: JSON!
facets: [JSON]
metadata: SnootyMetadata @link
componentNames: [String!]
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/Breadcrumbs/BreadcrumbContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ const crumbObjectShape = {
};

BreadcrumbContainer.propTypes = {
breadcrumbs: PropTypes.shape(crumbObjectShape).isRequired,
breadcrumbs: PropTypes.arrayOf(PropTypes.shape(crumbObjectShape)).isRequired,
};

export default BreadcrumbContainer;
144 changes: 81 additions & 63 deletions src/components/Code/Code.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { css } from '@emotion/react';
import React, { useCallback, useContext } from 'react';
import React, { useCallback, useContext, useMemo } from 'react';
import PropTypes from 'prop-types';
import styled from '@emotion/styled';
import { default as CodeBlock } from '@leafygreen-ui/code';
Expand All @@ -12,6 +12,8 @@ import { TabContext } from '../Tabs/tab-context';
import { reportAnalytics } from '../../utils/report-analytics';
import { getLanguage } from '../../utils/get-language';
import { DRIVER_ICON_MAP } from '../icons/DriverIconMap';
import { SoftwareSourceCodeSd } from '../../utils/structured-data';
import { usePageContext } from '../../context/page-context';
import { baseCodeStyle, borderCodeStyle, lgStyles } from './styles/codeStyle';
import { CodeContext } from './code-context';

Expand Down Expand Up @@ -41,6 +43,7 @@ const Code = ({
const { setActiveTab } = useContext(TabContext);
const { languageOptions, codeBlockLanguage } = useContext(CodeContext);
const { darkMode } = useDarkMode();
const { slug } = usePageContext();
const code = value;
let language = (languageOptions?.length > 0 && codeBlockLanguage) || getLanguage(lang);

Expand Down Expand Up @@ -85,77 +88,92 @@ const Code = ({
reportAnalytics('CodeblockCopied', { code });
}, [code]);

const softwareSourceCodeSd = useMemo(() => {
const sd = new SoftwareSourceCodeSd({ code, lang, slug });
return sd.isValid() ? sd.toString() : undefined;
}, [code, lang, slug]);

return (
<div
css={css`
${baseCodeStyle}
// Remove whitespace when copyable false
> div > div {
display: grid;
grid-template-columns: ${!copyable && (languageOptions?.length === 0 || language === 'none')
? 'auto 0px !important'
: 'code panel'};
}
> div {
border-top-left-radius: ${captionBorderRadius};
border-top-right-radius: ${captionBorderRadius};
display: grid;
border-color: ${palette.gray.light2};
.dark-theme & {
border-color: ${palette.gray.dark2};
<>
{softwareSourceCodeSd && (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: softwareSourceCodeSd,
}}
/>
)}
<div
css={css`
${baseCodeStyle}
// Remove whitespace when copyable false
> div > div {
display: grid;
grid-template-columns: ${!copyable && (languageOptions?.length === 0 || language === 'none')
? 'auto 0px !important'
: 'code panel'};
}
}
pre {
background-color: ${palette.gray.light3};
color: ${palette.black};
> div {
border-top-left-radius: ${captionBorderRadius};
border-top-right-radius: ${captionBorderRadius};
display: grid;
border-color: ${palette.gray.light2};
.dark-theme & {
background-color: ${palette.black};
color: ${palette.gray.light3};
.dark-theme & {
border-color: ${palette.gray.dark2};
}
}
}
[data-testid='leafygreen-code-panel'] {
background-color: ${palette.white};
border-color: ${palette.gray.light2};
pre {
background-color: ${palette.gray.light3};
color: ${palette.black};
.dark-theme & {
background-color: ${palette.gray.dark2};
border-color: ${palette.gray.dark2};
.dark-theme & {
background-color: ${palette.black};
color: ${palette.gray.light3};
}
}
}
${lgStyles}
`}
>
{captionSpecified && (
<div>
<CaptionContainer style={{ '--border-color': darkMode ? palette.gray.dark2 : palette.gray.light2 }}>
<Caption style={{ '--color': darkMode ? palette.gray.light2 : palette.gray.dark1 }}>{caption}</Caption>
</CaptionContainer>
</div>
)}
<CodeBlock
copyable={copyable}
highlightLines={emphasizeLines}
language={language}
languageOptions={languageOptions}
onChange={(selectedOption) => {
setActiveTab({ drivers: selectedOption.id });
}}
onCopy={reportCodeCopied}
showLineNumbers={linenos}
showCustomActionButtons={sourceSpecified}
customActionButtons={customActionButtonList}
lineNumberStart={lineno_start}
[data-testid='leafygreen-code-panel'] {
background-color: ${palette.white};
border-color: ${palette.gray.light2};
.dark-theme & {
background-color: ${palette.gray.dark2};
border-color: ${palette.gray.dark2};
}
}
${lgStyles}
`}
>
{code}
</CodeBlock>
</div>
{captionSpecified && (
<div>
<CaptionContainer style={{ '--border-color': darkMode ? palette.gray.dark2 : palette.gray.light2 }}>
<Caption style={{ '--color': darkMode ? palette.gray.light2 : palette.gray.dark1 }}>{caption}</Caption>
</CaptionContainer>
</div>
)}
<CodeBlock
copyable={copyable}
highlightLines={emphasizeLines}
language={language}
languageOptions={languageOptions}
onChange={(selectedOption) => {
setActiveTab({ drivers: selectedOption.id });
}}
onCopy={reportCodeCopied}
showLineNumbers={linenos}
showCustomActionButtons={sourceSpecified}
customActionButtons={customActionButtonList}
lineNumberStart={lineno_start}
>
{code}
</CodeBlock>
</div>
</>
);
};

Expand Down
16 changes: 9 additions & 7 deletions src/components/Code/CodeIO.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ const outputButtonStyling = LeafyCss`
margin: 8px;
`;

const outputContainerStyle = (showOutput) => LeafyCss`
${!showOutput && 'display: none;'}
`;

const CodeIO = ({ nodeData: { children }, ...rest }) => {
const { darkMode } = useDarkMode();
const needsIOToggle = children.length === 2;
Expand All @@ -32,12 +36,8 @@ const CodeIO = ({ nodeData: { children }, ...rest }) => {
const outputBorderRadius = !showOutput ? '12px' : '0px';
const singleInputBorderRadius = onlyInputSpecified ? '12px' : '0px';

const handleClick = (e) => {
if (showOutput) {
setShowOutput(false);
} else {
setShowOutput(true);
}
const handleClick = () => {
setShowOutput((val) => !val);
};

if (children.length === 0) {
Expand Down Expand Up @@ -77,7 +77,9 @@ const CodeIO = ({ nodeData: { children }, ...rest }) => {
{buttonText}
</Button>
</IOToggle>
{showOutput && <Output nodeData={children[1]} />}
<div className={outputContainerStyle(showOutput)}>
<Output nodeData={children[1]} />
</div>
</>
)}
{onlyInputSpecified && <Input nodeData={children[0]} />}
Expand Down
67 changes: 42 additions & 25 deletions src/components/Code/Output.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import React from 'react';
import React, { useMemo } from 'react';
import styled from '@emotion/styled';
import PropTypes from 'prop-types';
import { default as CodeBlock } from '@leafygreen-ui/code';
import { useDarkMode } from '@leafygreen-ui/leafygreen-provider';
import { palette } from '@leafygreen-ui/palette';
import { getLanguage } from '../../utils/get-language';
import { SoftwareSourceCodeSd } from '../../utils/structured-data';
import { usePageContext } from '../../context/page-context';

const OutputContainer = styled.div`
> div > * {
Expand All @@ -27,36 +29,51 @@ const OutputContainer = styled.div`
}
`;

const Output = ({ nodeData: { children }, ...rest }) => {
const Output = ({ nodeData: { children } }) => {
const { darkMode } = useDarkMode();
const { emphasize_lines, value, linenos, lang, lineno_start } = children[0];
const language = getLanguage(lang);
const { slug } = usePageContext();
const softwareSourceCodeSd = useMemo(() => {
const sd = new SoftwareSourceCodeSd({ code: value, lang, slug });
return sd.isValid() ? sd.toString() : undefined;
}, [value, lang, slug]);

return (
<OutputContainer
style={
darkMode
? {
'--code-container-border': 'none',
'--code-pre-border': `1px solid ${palette.gray.dark2}`,
}
: {
'--code-container-border': 'initial',
'--code-pre-border': `none`,
}
}
>
<CodeBlock
highlightLines={emphasize_lines}
language={language}
showLineNumbers={linenos}
darkMode={true}
copyable={false}
lineNumberStart={lineno_start}
<>
{softwareSourceCodeSd && (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: softwareSourceCodeSd,
}}
/>
)}
<OutputContainer
style={
darkMode
? {
'--code-container-border': 'none',
'--code-pre-border': `1px solid ${palette.gray.dark2}`,
}
: {
'--code-container-border': 'initial',
'--code-pre-border': `none`,
}
}
>
{value}
</CodeBlock>
</OutputContainer>
<CodeBlock
highlightLines={emphasize_lines}
language={language}
showLineNumbers={linenos}
darkMode={true}
copyable={false}
lineNumberStart={lineno_start}
>
{value}
</CodeBlock>
</OutputContainer>
</>
);
};

Expand Down
37 changes: 20 additions & 17 deletions src/components/Collapsible/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Icon from '@leafygreen-ui/icon';
import IconButton from '@leafygreen-ui/icon-button';
import { cx } from '@leafygreen-ui/emotion';
import { Body } from '@leafygreen-ui/typography';
import { HeadingContextProvider } from '../../context/heading-context';
import { findAllNestedAttribute } from '../../utils/find-all-nested-attribute';
import { isBrowser } from '../../utils/is-browser';
import { reportAnalytics } from '../../utils/report-analytics';
Expand Down Expand Up @@ -65,25 +66,27 @@ const Collapsible = ({ nodeData: { children, options }, sectionDepth, ...rest })
}, [childrenHashIds, hash, open]);

return (
<Box className={cx('collapsible', collapsibleStyle)}>
<Box className={cx(headerContainerStyle)}>
<Box>
{/* Adding 1 to reflect logic in parser, but want to show up as H2 for SEO reasons */}
<Heading className={cx(headerStyle)} sectionDepth={sectionDepth + 1} as={2} nodeData={headingNodeData}>
{heading}
</Heading>
<Body baseFontSize={13}>{subHeading}</Body>
<HeadingContextProvider ignoreNextHeading={true} heading={heading}>
<Box className={cx('collapsible', collapsibleStyle)}>
<Box className={cx(headerContainerStyle)}>
<Box>
{/* Adding 1 to reflect logic in parser, but want to show up as H2 for SEO reasons */}
<Heading className={cx(headerStyle)} sectionDepth={sectionDepth + 1} as={2} nodeData={headingNodeData}>
{heading}
</Heading>
<Body baseFontSize={13}>{subHeading}</Body>
</Box>
<IconButton className={iconStyle} aria-labelledby={'Expand the collapsed content'} onClick={onIconClick}>
<Icon glyph={open ? 'ChevronDown' : 'ChevronRight'} />
</IconButton>
</Box>
<Box className={cx(innerContentStyle(open))}>
{children.map((c, i) => (
<ComponentFactory nodeData={c} key={i} sectionDepth={sectionDepth} {...rest}></ComponentFactory>
))}
</Box>
<IconButton className={iconStyle} aria-labelledby={'Expand the collapsed content'} onClick={onIconClick}>
<Icon glyph={open ? 'ChevronDown' : 'ChevronRight'} />
</IconButton>
</Box>
<Box className={cx(innerContentStyle(open))}>
{children.map((c, i) => (
<ComponentFactory nodeData={c} key={i} sectionDepth={sectionDepth} {...rest}></ComponentFactory>
))}
</Box>
</Box>
</HeadingContextProvider>
);
};

Expand Down
Loading

0 comments on commit 5c07775

Please sign in to comment.