diff --git a/package.json b/package.json index 34f0eaf172..d5bc0b417c 100644 --- a/package.json +++ b/package.json @@ -125,6 +125,7 @@ "jest": "^21.1.0", "jsonml.js": "^0.1.0", "lint-staged": "^6.0.0", + "lz-string": "^1.4.4", "majo": "^0.4.1", "mockdate": "^2.0.1", "moment-timezone": "^0.5.5", diff --git a/site/theme/en-US.js b/site/theme/en-US.js index 10753f2ba7..97fd228d99 100644 --- a/site/theme/en-US.js +++ b/site/theme/en-US.js @@ -20,6 +20,7 @@ module.exports = { 'app.demo.copy': 'Copy code', 'app.demo.copied': 'Copied!', 'app.demo.codepen': 'Open in CodePen', + 'app.demo.codesandbox': 'Open in CodeSandbox', 'app.demo.riddle': 'Open in Riddle', 'app.home.slogan': 'A UI Design Language', 'app.home.introduce': 'Introduce', diff --git a/site/theme/static/demo.less b/site/theme/static/demo.less index 0bbdc32c07..b9259641b7 100644 --- a/site/theme/static/demo.less +++ b/site/theme/static/demo.less @@ -231,8 +231,21 @@ overflow: hidden; } + &-codesandbox { + background: transparent url("https://gw.alipayobjects.com/zos/rmsportal/aaYmtdDyHSCkXyLZVgGK.svg") center / 14px no-repeat; + width: 20px; + height: 20px; + cursor: pointer; + opacity: 0; + transition: all .3s; + border: 0; + text-indent: -9999px; + overflow: hidden; + } + .highlight-wrapper:hover &-code-copy, .highlight-wrapper:hover &-codepen, + .highlight-wrapper:hover &-codesandbox, .highlight-wrapper:hover &-riddle { opacity: 1; } diff --git a/site/theme/template/Content/Demo.jsx b/site/theme/template/Content/Demo.jsx index bd77306390..410dc5a534 100644 --- a/site/theme/template/Content/Demo.jsx +++ b/site/theme/template/Content/Demo.jsx @@ -5,11 +5,19 @@ import PropTypes from 'prop-types'; import { FormattedMessage } from 'react-intl'; import CopyToClipboard from 'react-copy-to-clipboard'; import classNames from 'classnames'; +import LZString from 'lz-string'; import { Icon, Tooltip } from 'antd'; import EditButton from './EditButton'; import BrowserFrame from '../BrowserFrame'; import { ping } from '../utils'; +function compress(string) { + return LZString.compressToBase64(string) + .replace(/\+/g, '-') // Convert '+' to '-' + .replace(/\//g, '_') // Convert '/' to '_' + .replace(/=+$/, ''); // Remove ending '=' +} + export default class Demo extends React.Component { static contextTypes = { intl: PropTypes.object, @@ -117,13 +125,14 @@ export default class Demo extends React.Component { }); const prefillStyle = `@import 'antd/dist/antd.css';\n\n${style || ''}`.replace(new RegExp(`#${meta.id}\\s*`, 'g'), ''); + const html = `
+`; const codepenPrefillConfig = { title: `${localizedTitle} - Ant Design Demo`, - html: ` -`, + html, js: state.sourceCode.replace(/import\s+\{\s+(.*)\s+\}\s+from\s+'antd';/, 'const { $1 } = antd;'), css: prefillStyle, editors: '001', @@ -141,6 +150,37 @@ export default class Demo extends React.Component { js: state.sourceCode, css: prefillStyle, }; + const dependencies = state.sourceCode.split('\n').reduce((acc, line) => { + const matches = line.match(/import .+? from '(.+)';$/); + if (matches && matches[1]) { + acc[matches[1]] = 'latest'; + } + return acc; + }, { react: 'latest', 'react-dom': 'latest' }); + const codesanboxPrefillConfig = { + files: { + 'package.json': { + content: { + dependencies, + }, + }, + 'index.css': { + content: (style || '').replace(new RegExp(`#${meta.id}\\s*`, 'g'), ''), + }, + 'index.js': { + content: ` +import React from 'react'; +import ReactDOM from 'react-dom'; +import 'antd/dist/antd.css'; +import './index.css'; +${state.sourceCode.replace('mountNode', 'document.getElementById(\'container\')')} + `, + }, + 'index.html': { + content: html, + }, + }, + }; return (