Skip to content

Commit

Permalink
docs: prevent highlight code initially (ant-design#44344)
Browse files Browse the repository at this point in the history
  • Loading branch information
afc163 committed Aug 22, 2023
1 parent 70d9a90 commit 0295322
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 77 deletions.
48 changes: 6 additions & 42 deletions .dumi/theme/builtins/Previewer/CodePreviewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ import type { Project } from '@stackblitz/sdk';
import stackblitzSdk from '@stackblitz/sdk';
import classNames from 'classnames';
import { FormattedMessage, useSiteData } from 'dumi';
import toReactElement from 'jsonml-to-react-element';
import JsonML from 'jsonml.js/lib/utils';
import LZString from 'lz-string';
import Prism from 'prismjs';
import React, { useContext, useEffect, useRef, useState } from 'react';
import CopyToClipboard from 'react-copy-to-clipboard';
import { Alert, Badge, Space, Tooltip } from 'antd';
Expand All @@ -31,28 +28,6 @@ import { ping } from '../../utils';

const { ErrorBoundary } = Alert;

function toReactComponent(jsonML: any) {
return toReactElement(jsonML, [
[
(node: any) => JsonML.isElement(node) && JsonML.getTagName(node) === 'pre',
(node: any, index: any) => {
// ref: https://github.com/benjycui/bisheng/blob/master/packages/bisheng/src/bisheng-plugin-highlight/lib/browser.js#L7
const attr = JsonML.getAttributes(node);
return React.createElement(
'pre',
{
key: index,
className: `language-${attr.lang}`,
},
React.createElement('code', {
dangerouslySetInnerHTML: { __html: attr.highlighted },
}),
);
},
],
]);
}

function compress(string: string): string {
return LZString.compressToBase64(string)
.replace(/\+/g, '-') // Convert '+' to '-'
Expand Down Expand Up @@ -130,13 +105,6 @@ const CodePreviewer: React.FC<AntdPreviewerProps> = (props) => {

const [showOnlineUrl, setShowOnlineUrl] = useState<boolean>(false);

const highlightedCodes = {
jsx: Prism.highlight(jsx, Prism.languages.javascript, 'jsx'),
tsx: Prism.highlight(entryCode, Prism.languages.javascript, 'jsx'),
};

const highlightedStyle = style ? Prism.highlight(style, Prism.languages.css, 'css') : '';

useEffect(() => {
const regexp = /preview-(\d+)-ant-design/; // matching PR preview addresses
setShowOnlineUrl(
Expand Down Expand Up @@ -538,17 +506,11 @@ createRoot(document.getElementById('container')).render(<Demo />);
{codeExpand && (
<section className={highlightClass} key="code">
<CodePreview
codes={highlightedCodes}
toReactComponent={toReactComponent}
sourceCode={entryCode}
jsxCode={jsx}
styleCode={style}
onCodeTypeChange={(type) => setCodeType(type)}
/>
{highlightedStyle ? (
<div key="style" className="highlight">
<pre>
<code className="css" dangerouslySetInnerHTML={{ __html: highlightedStyle }} />
</pre>
</div>
) : null}
</section>
)}
</section>
Expand All @@ -560,7 +522,9 @@ createRoot(document.getElementById('container')).render(<Demo />);
// resulting in some response delays like following issue:
// https://github.com/ant-design/ant-design/issues/39995
// So we insert style tag into head tag.
if (!style) return;
if (!style) {
return;
}
const styleTag = document.createElement('style');
styleTag.type = 'text/css';
styleTag.innerHTML = style;
Expand Down
38 changes: 21 additions & 17 deletions .dumi/theme/builtins/Previewer/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import React, { Suspense } from 'react';
import type { IPreviewerProps } from 'dumi';
import { Skeleton } from 'antd';
import { Skeleton, Alert } from 'antd';
import { createStyles } from 'antd-style';

const { ErrorBoundary } = Alert;

const Previewer = React.lazy(() => import('./Previewer'));

const useStyle = createStyles(({ css }) => ({
Expand All @@ -16,21 +18,23 @@ const useStyle = createStyles(({ css }) => ({
export default (props: IPreviewerProps) => {
const { styles } = useStyle();
return (
<Suspense
fallback={
<Skeleton.Node
active
className={styles.skeletonWrapper}
style={{
width: '100%',
height: '100%',
}}
>
{' '}
</Skeleton.Node>
}
>
<Previewer {...props} />
</Suspense>
<ErrorBoundary>
<Suspense
fallback={
<Skeleton.Node
active
className={styles.skeletonWrapper}
style={{
width: '100%',
height: '100%',
}}
>
{' '}
</Skeleton.Node>
}
>
<Previewer {...props} />
</Suspense>
</ErrorBoundary>
);
};
100 changes: 82 additions & 18 deletions .dumi/theme/common/CodePreview.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,101 @@
import React from 'react';
import React, { useEffect, useMemo } from 'react';
import Prism from 'prismjs';
import toReactElement from 'jsonml-to-react-element';
import JsonML from 'jsonml.js/lib/utils';
import { Tabs } from 'antd';

const LANGS = {
tsx: 'TypeScript',
jsx: 'JavaScript',
style: 'CSS',
};

interface CodePreviewProps {
codes?: Record<PropertyKey, string>;
toReactComponent?: (node: any) => React.ReactNode;
sourceCode?: string;
jsxCode?: string;
styleCode?: string;
onCodeTypeChange?: (activeKey: string) => void;
}

const CodePreview: React.FC<CodePreviewProps> = ({ toReactComponent, codes, onCodeTypeChange }) => {
const langList = Object.keys(codes).sort().reverse();
function toReactComponent(jsonML: any) {
return toReactElement(jsonML, [
[
(node: any) => JsonML.isElement(node) && JsonML.getTagName(node) === 'pre',
(node: any, index: any) => {
// ref: https://github.com/benjycui/bisheng/blob/master/packages/bisheng/src/bisheng-plugin-highlight/lib/browser.js#L7
const attr = JsonML.getAttributes(node);
return React.createElement(
'pre',
{
key: index,
className: `language-${attr.lang}`,
},
React.createElement('code', {
dangerouslySetInnerHTML: { __html: attr.highlighted },
}),
);
},
],
]);
}

const CodePreview: React.FC<CodePreviewProps> = ({
sourceCode = '',
jsxCode = '',
styleCode = '',
onCodeTypeChange,
}) => {
// 避免 Tabs 数量不稳定的闪动问题
const initialCodes = {};
if (sourceCode) {
initialCodes.tsx = '';
}
if (jsxCode) {
initialCodes.jsx = '';
}
if (styleCode) {
initialCodes.style = '';
}
const [highlightedCodes, setHighlightedCodes] = React.useState(initialCodes);

useEffect(() => {
const codes = {
tsx: Prism.highlight(sourceCode, Prism.languages.javascript, 'jsx'),
jsx: Prism.highlight(jsxCode, Prism.languages.javascript, 'jsx'),
style: Prism.highlight(styleCode, Prism.languages.css, 'css'),
};
// 去掉空的代码类型
Object.keys(codes).forEach((key) => {
if (!codes[key]) {
delete codes[key];
}
});
setHighlightedCodes(codes);
}, [jsxCode, sourceCode, styleCode]);

const langList = Object.keys(highlightedCodes);
const items = useMemo(
() =>
langList.map((lang) => ({
label: LANGS[lang],
key: lang,
children: toReactComponent(['pre', { lang, highlighted: highlightedCodes[lang] }]),
})),
[JSON.stringify(highlightedCodes)],
);

if (!langList.length) {
return null;
}

if (langList.length === 1) {
return toReactComponent([
'pre',
{ lang: langList[0], highlighted: codes[langList[0]], className: 'highlight' },
{ lang: langList[0], highlighted: highlightedCodes[langList[0]], className: 'highlight' },
]);
}
return (
<Tabs
centered
className="highlight"
onChange={onCodeTypeChange}
items={langList.map((lang) => ({
label: LANGS[lang],
key: lang,
children: toReactComponent(['pre', { lang, highlighted: codes[lang] }]),
}))}
/>
);

return <Tabs centered className="highlight" onChange={onCodeTypeChange} items={items} />;
};

export default CodePreview;

0 comments on commit 0295322

Please sign in to comment.