diff --git a/package.json b/package.json index 3dc9f73373e8..504f874753d8 100644 --- a/package.json +++ b/package.json @@ -160,9 +160,9 @@ "dist": "antd-tools run dist", "compile": "antd-tools run compile", "tsc": "tsc", - "start": "cross-env NODE_ENV=development bisheng start -c ./site/bisheng.config.js --no-livereload", + "start": "cross-env NODE_ENV=development node ./scripts/generateColorLess.js && bisheng start -c ./site/bisheng.config.js --no-livereload", "site": "cross-env NODE_ENV=production bisheng build --ssr -c ./site/bisheng.config.js", - "deploy": "antd-tools run clean && npm run site && bisheng gh-pages --push-only", + "deploy": "antd-tools run clean && npm run site && node ./scripts/generateColorLess.js && bisheng gh-pages --push-only", "pub": "antd-tools run pub", "prepublish": "antd-tools run guard", "pre-publish": "npm run test-all && node ./scripts/prepub", diff --git a/scripts/generateColorLess.js b/scripts/generateColorLess.js new file mode 100644 index 000000000000..0dcad3ac11a2 --- /dev/null +++ b/scripts/generateColorLess.js @@ -0,0 +1,95 @@ +#!/usr/bin/env node + +const fs = require('fs'); +const path = require('path'); +const glob = require('glob'); +const postcss = require('postcss'); +const less = require('less'); + +const COLOR_MAP = { + '#ecf6fd': 'color(~`colorPalette("@{primary-color}", 1)`)', // @primary-1 + '#d2eafb': 'color(~`colorPalette("@{primary-color}", 2)`)', // @primary-2 + '#49a9ee': 'color(~`colorPalette("@{primary-color}", 5)`)', // @primary-5 + '#108ee9': '@primary-color', + '#0e77ca': 'color(~`colorPalette("@{primary-color}", 7)`)', // @primary-7 + '#40a5ed': 'tint(@primary-color, 20%)', + '#70bbf2': 'tint(@primary-color, 40%)', + '#88c7f4': 'tint(@primary-color, 50%)', + '#9fd2f6': 'tint(@primary-color, 60%)', + 'rgba(16, 142, 233, 0.2)': 'fadeout(@primary-color, 80%)', +}; + +const reducePlugin = postcss.plugin('reducePlugin', () => { + const cleanRule = (rule) => { + let removeRule = true; + rule.walkDecls((decl) => { + if ( + !decl.prop.includes('color') && + !decl.prop.includes('background') && + !decl.prop.includes('border') && + !decl.prop.includes('box-shadow') + ) { + decl.remove(); + } else { + removeRule = false; + } + }); + if (removeRule) { + rule.remove(); + } + }; + return (css) => { + css.walkAtRules((atRule) => { + atRule.remove(); + }); + + css.walkRules(cleanRule); + + css.walkComments(c => c.remove()); + }; +}); + +async function generateCss() { + const antd = path.resolve(__dirname, '../'); + const entry = path.join(antd, 'components/style/index.less'); + let content = fs.readFileSync(entry).toString(); + const styles = glob.sync(path.join(antd, 'components/*/style/index.less')); + content += '\n'; + styles.forEach((style) => { + content += `@import "${style}";\n`; + }); + content += `@import "${path.join(antd, 'site/theme/static/index.less')}";\n`; + fs.writeFileSync('/tmp/style.less', content); + + let result = (await less.render.call(less, content, { + paths: [path.join(antd, 'components/style')], + })).css; + + result = (await postcss([ + reducePlugin, + ]).process(result, { parser: less.parser, from: entry })).css; + + Object.keys(COLOR_MAP).forEach((key) => { + result = result.replace(new RegExp(key, 'g'), COLOR_MAP[key]); + }); + + const bezierEasing = fs.readFileSync(path.join(antd, 'components/style/color/bezierEasing.less')).toString(); + const tinyColor = fs.readFileSync(path.join(antd, 'components/style/color/tinyColor.less')).toString(); + const colorPalette = fs.readFileSync(path.join(antd, 'components/style/color/colorPalette.less')) + .toString() + .replace('@import "bezierEasing";', '') + .replace('@import "tinyColor";', ''); + + result = `${colorPalette}\n${result}`; + result = `${tinyColor}\n${result}`; + result = `${bezierEasing}\n${result}`; + result = `@primary-color: #108ee9;\n${result}`; + + const siteDir = path.resolve(__dirname, '../_site'); + if (!fs.existsSync(siteDir)) { + fs.mkdirSync(siteDir); + } + fs.writeFileSync(path.resolve(__dirname, '../_site/color.less'), result); +} + +generateCss(); diff --git a/site/theme/static/template.html b/site/theme/static/template.html index 8f6db60736b7..dc2f58a09b69 100644 --- a/site/theme/static/template.html +++ b/site/theme/static/template.html @@ -61,6 +61,7 @@ + diff --git a/site/theme/template/Layout/Footer.jsx b/site/theme/template/Layout/Footer.jsx index 32dea35339f7..655e46c779d7 100644 --- a/site/theme/template/Layout/Footer.jsx +++ b/site/theme/template/Layout/Footer.jsx @@ -1,14 +1,15 @@ import React from 'react'; import { FormattedMessage, injectIntl } from 'react-intl'; import { Modal, Icon, message } from 'antd'; -import reqwest from 'reqwest'; -import { isLocalStorageNameSupported } from '../utils'; +import { isLocalStorageNameSupported, loadScript } from '../utils'; import ColorPicker from '../Color/ColorPicker'; class Footer extends React.Component { constructor(props) { super(props); + this.lessLoaded = false; + this.state = { color: '#108ee9', }; @@ -32,23 +33,29 @@ class Footer extends React.Component { } handleColorChange = (color) => { - const { messages } = this.props.intl; - reqwest({ - url: 'https://ant-design-theme.now.sh/compile', - method: 'post', - data: { - variables: { - '@primary-color': color, - }, - }, - }).then((data) => { - message.success(messages['app.footer.primary-color-changed']); - this.setState({ color }); - const head = document.querySelector('head'); - const style = document.createElement('style'); - style.innerText = data; - head.appendChild(style); - }); + const changeColor = () => { + const { messages } = this.props.intl; + window.less.modifyVars({ + '@primary-color': color, + }).then(() => { + message.success(messages['app.footer.primary-color-changed']); + this.setState({ color }); + }); + }; + + const lessUrl = 'https://cdnjs.cloudflare.com/ajax/libs/less.js/2.7.2/less.min.js'; + + if (this.lessLoaded) { + changeColor(); + } else { + window.less = { + async: true, + }; + loadScript(lessUrl).then(() => { + this.lessLoaded = true; + changeColor(); + }); + } } infoNewVersion() { diff --git a/site/theme/template/utils.jsx b/site/theme/template/utils.jsx index a9125a277592..bb9104dbb9d6 100644 --- a/site/theme/template/utils.jsx +++ b/site/theme/template/utils.jsx @@ -64,3 +64,14 @@ export function isLocalStorageNameSupported() { return false; } } + +export function loadScript(src) { + return new Promise((resolve, reject) => { + const script = document.createElement('script'); + script.type = 'text/javascript'; + script.src = src; + script.onload = resolve; + script.onerror = reject; + document.head.appendChild(script); + }); +}