refactor: replace sass with postcss

This commit is contained in:
Haishan 2019-04-14 22:56:14 +08:00
parent 4a4f58c88a
commit 7dac1d44c7
53 changed files with 181 additions and 953 deletions

View file

@ -81,11 +81,12 @@
"husky": "^1.3.0", "husky": "^1.3.0",
"lint-staged": "^8.1.3", "lint-staged": "^8.1.3",
"mini-css-extract-plugin": "^0.5.0", "mini-css-extract-plugin": "^0.5.0",
"node-sass": "^4.10.0", "postcss-extend-rule": "^2.0.0",
"postcss-import": "^12.0.1",
"postcss-loader": "^3.0.0", "postcss-loader": "^3.0.0",
"postcss-nested": "^4.1.2",
"prettier": "^1.16.4", "prettier": "^1.16.4",
"react-hot-loader": "^4.6.3", "react-hot-loader": "^4.6.3",
"sass-loader": "^7.0.1",
"style-loader": "^0.23.0", "style-loader": "^0.23.0",
"svg-sprite-loader": "^4.1.2", "svg-sprite-loader": "^4.1.2",
"terser-webpack-plugin": "^1.2.2", "terser-webpack-plugin": "^1.2.2",

View file

@ -5,7 +5,7 @@ import Field from 'c/Field';
import Button from 'c/Button'; import Button from 'c/Button';
import SvgYacd from './SvgYacd'; import SvgYacd from './SvgYacd';
import s0 from './APIConfig.module.scss'; import s0 from './APIConfig.module.css';
import { getClashAPIConfig, updateClashAPIConfig } from 'd/app'; import { getClashAPIConfig, updateClashAPIConfig } from 'd/app';

View file

@ -7,7 +7,7 @@ import APIConfig from 'c/APIConfig';
import { closeModal } from 'd/modals'; import { closeModal } from 'd/modals';
import { fetchConfigs } from 'd/configs'; import { fetchConfigs } from 'd/configs';
import s0 from './APIDiscovery.module.scss'; import s0 from './APIDiscovery.module.css';
const mapStateToProps = s => ({ const mapStateToProps = s => ({
modals: s.modals modals: s.modals

View file

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import s0 from 'c/Button.module.scss'; import s0 from 'c/Button.module.css';
const noop = () => {}; const noop = () => {};
const Button = React.memo(function Button({ label, onClick = noop }) { const Button = React.memo(function Button({ label, onClick = noop }) {

View file

@ -14,7 +14,7 @@
background: #387cec; background: #387cec;
border: 1px solid #387cec; border: 1px solid #387cec;
color: #fff; color: #fff;
// background: darken(#555, 3%); /* background: darken(#555, 3%); */
} }
&:active { &:active {
transform: scale(0.97); transform: scale(0.97);

View file

@ -8,7 +8,7 @@ import ContentHeader from 'c/ContentHeader';
import Switch from 'c/Switch'; import Switch from 'c/Switch';
import ToggleSwitch from 'c/ToggleSwitch'; import ToggleSwitch from 'c/ToggleSwitch';
import Input from 'c/Input'; import Input from 'c/Input';
import s0 from 'c/Config.module.scss'; import s0 from 'c/Config.module.css';
const optionsRule = [ const optionsRule = [
{ {

View file

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import s0 from './ContentHeader.module.scss'; import s0 from './ContentHeader.module.css';
function ContentHeader({ title }) { function ContentHeader({ title }) {
return ( return (

View file

@ -3,7 +3,7 @@ import Icon from 'c/Icon';
import SvgYacd from './SvgYacd'; import SvgYacd from './SvgYacd';
import github from 's/github.svg'; import github from 's/github.svg';
import s0 from './ErrorBoundaryFallback.module.scss'; import s0 from './ErrorBoundaryFallback.module.css';
const yacdRepoIssueUrl = 'https://github.com/haishanh/yacd/issues'; const yacdRepoIssueUrl = 'https://github.com/haishanh/yacd/issues';
function ErrorBoundaryFallback() { function ErrorBoundaryFallback() {

View file

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import cx from 'classnames'; import cx from 'classnames';
import s from './Field.module.scss'; import s from './Field.module.css';
const { useCallback } = React; const { useCallback } = React;

View file

@ -4,7 +4,7 @@
input { input {
-webkit-appearance: none; -webkit-appearance: none;
background-color: transparent; background-color: transparent;
// background-color: var(--color-input-bg); /* background-color: var(--color-input-bg); */
background-image: none; background-image: none;
border: none; border: none;
border-radius: 0; border-radius: 0;

View file

@ -4,7 +4,7 @@ import ContentHeader from 'c/ContentHeader';
import TrafficChart from 'c/TrafficChart'; import TrafficChart from 'c/TrafficChart';
import TrafficNow from 'c/TrafficNow'; import TrafficNow from 'c/TrafficNow';
import Loading from 'c/Loading'; import Loading from 'c/Loading';
import s0 from 'c/Home.module.scss'; import s0 from 'c/Home.module.css';
export default function Home() { export default function Home() {
return ( return (

View file

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import s0 from './Input.module.scss'; import s0 from './Input.module.css';
export default function Input(props) { export default function Input(props) {
return <input className={s0.input} {...props} />; return <input className={s0.input} {...props} />;

View file

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import s0 from './Loading.module.scss'; import s0 from './Loading.module.css';
const Loading = ({ height }) => { const Loading = ({ height }) => {
const style = height ? { height } : {}; const style = height ? { height } : {};

View file

@ -1,7 +1,3 @@
// $color1: #2a477a;
$color1: #dddddd;
$size: 40px;
.loading { .loading {
width: 100%; width: 100%;
@ -12,10 +8,12 @@ $size: 40px;
} }
.pulse { .pulse {
width: $size; --color1: #dddddd;
height: $size; --size: 40px;
width: var(--size);
height: var(--size);
margin: 10px; margin: 10px;
background-color: $color1; background-color: var(--color1);
border-radius: 100%; border-radius: 100%;
animation: pulseScaleOut 1s infinite ease-in-out; animation: pulseScaleOut 1s infinite ease-in-out;
} }

View file

@ -13,7 +13,7 @@ import { fetchLogs } from '../api/logs';
import LogSearch from './LogSearch'; import LogSearch from './LogSearch';
import { getLogsForDisplay, appendLog } from 'd/logs'; import { getLogsForDisplay, appendLog } from 'd/logs';
import s0 from 'c/Logs.module.scss'; import s0 from 'c/Logs.module.css';
const paddingBottom = 30; const paddingBottom = 30;
const colors = { const colors = {
debug: 'none', debug: 'none',

View file

@ -1,6 +1,3 @@
$colorf: #eee;
$heightHeader: 76px;
.logMeta { .logMeta {
display: flex; display: flex;
align-items: center; align-items: center;
@ -10,7 +7,7 @@ $heightHeader: 76px;
} }
.logType { .logType {
color: $colorf; color: #eee;
flex-shrink: 0; flex-shrink: 0;
text-align: center; text-align: center;
width: 66px; width: 66px;
@ -32,13 +29,13 @@ $heightHeader: 76px;
font-family: 'Roboto Mono', Menlo, monospace; font-family: 'Roboto Mono', Menlo, monospace;
align-items: center; align-items: center;
padding: 8px 0; padding: 8px 0;
// force wrap /* force wrap */
width: 100%; width: 100%;
white-space: pre; white-space: pre;
overflow: auto; overflow: auto;
} }
////////// /*******************/
.logsWrapper { .logsWrapper {
margin: 0; margin: 0;
@ -59,7 +56,7 @@ $heightHeader: 76px;
padding: 10px 40px; padding: 10px 40px;
} }
///////// /*******************/
.logPlaceholder { .logPlaceholder {
display: flex; display: flex;

View file

@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import Modal from 'react-modal'; import Modal from 'react-modal';
import cx from 'classnames'; import cx from 'classnames';
import s0 from './Modal.module.scss'; import s0 from './Modal.module.css';
function ModalAPIConfig({ function ModalAPIConfig({
isOpen, isOpen,

View file

@ -1,11 +1,9 @@
.overlay { .overlay {
position: fixed; position: fixed;
// z-index: 1000;
top: 0; top: 0;
right: 0; right: 0;
left: 0; left: 0;
bottom: 0; bottom: 0;
// background: rgba(255, 255, 255, 0.5);
background: #444; background: #444;
} }
@ -18,6 +16,5 @@
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
background: #444; background: #444;
padding: 20px; padding: 20px;
// border: 1px solid #ccc;
border-radius: 10px; border-radius: 10px;
} }

View file

@ -5,7 +5,7 @@ import ContentHeader from 'c/ContentHeader';
import ProxyGroup from 'c/ProxyGroup'; import ProxyGroup from 'c/ProxyGroup';
import Button from 'c/Button'; import Button from 'c/Button';
import s0 from 'c/Proxies.module.scss'; import s0 from 'c/Proxies.module.css';
import { import {
getProxies, getProxies,

View file

@ -14,7 +14,7 @@ import direct from 's/direct.svg';
import http from 's/http.svg'; import http from 's/http.svg';
import group from 's/group.svg'; import group from 's/group.svg';
import s0 from './Proxy.module.scss'; import s0 from './Proxy.module.css';
import { getDelay, getProxies } from 'd/proxies'; import { getDelay, getProxies } from 'd/proxies';

View file

@ -5,7 +5,7 @@ import { useActions, useStoreState } from 'm/store';
import Proxy from 'c/Proxy'; import Proxy from 'c/Proxy';
import s0 from './ProxyGroup.module.scss'; import s0 from './ProxyGroup.module.css';
import { getProxies, switchProxy } from 'd/proxies'; import { getProxies, switchProxy } from 'd/proxies';

View file

@ -20,7 +20,6 @@
width: 300px; width: 300px;
padding: 10px 5px; padding: 10px 5px;
transition: transform 0.2s ease-in-out; transition: transform 0.2s ease-in-out;
// transition: transform 0.4s ease, color 0.4s ease;
&.proxySelectable { &.proxySelectable {
cursor: pointer; cursor: pointer;
&:hover { &:hover {

View file

@ -1,7 +1,7 @@
import React, { useMemo } from 'react'; import React, { useMemo } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import s0 from './ProxyLatency.module.scss'; import s0 from './ProxyLatency.module.css';
const colorMap = { const colorMap = {
good: '#67C23A', good: '#67C23A',

View file

@ -1,8 +1,6 @@
.proxyLatency { .proxyLatency {
border-radius: 20px; border-radius: 20px;
margin: 10px 0; margin: 10px 0;
// padding: 3px 5px;
padding: 3px 0; padding: 3px 0;
color: #eee; color: #eee;
// background: #ccc;
} }

View file

@ -1,4 +1,3 @@
// this font-family only covers latin
@font-face { @font-face {
font-family: 'Roboto Mono'; font-family: 'Roboto Mono';
font-style: normal; font-style: normal;

View file

@ -10,8 +10,8 @@ import Logs from 'c/Logs';
import Config from 'c/Config'; import Config from 'c/Config';
import APIDiscovery from 'c/APIDiscovery'; import APIDiscovery from 'c/APIDiscovery';
import { store } from '../store/configureStore'; import { store } from '../store/configureStore';
import './Root.scss'; import './Root.css';
import s0 from './Root.module.scss'; import s0 from './Root.module.css';
const Proxies = React.lazy(() => const Proxies = React.lazy(() =>
import(/* webpackChunkName: "proxies" */ import(/* webpackChunkName: "proxies" */

View file

@ -0,0 +1,33 @@
.app {
display: flex;
background: var(--color-background);
color: var(--color-text);
min-height: 300px;
height: 100vh;
@media (max-width: 768px) {
flex-direction: column;
}
}
.content {
flex-grow: 1;
overflow: auto;
/*
$w: 7px;
&::-webkit-scrollbar {
width: $w;
}
&::-webkit-scrollbar-thumb {
border-radius: 20px;
background-color: rgba(221, 221, 221, 0.7);
}
&::-webkit-scrollbar-corner {
background: transparent;
}
*/
}

View file

@ -1,30 +0,0 @@
.app {
display: flex;
background: var(--color-background);
color: var(--color-text);
min-height: 300px;
height: 100vh;
@media (max-width: 768px) {
flex-direction: column;
}
}
.content {
flex-grow: 1;
overflow: auto;
// background: #202020;
// $w: 7px;
// &::-webkit-scrollbar {
// width: $w;
// }
// &::-webkit-scrollbar-thumb {
// border-radius: 20px;
// background-color: rgba(221, 221, 221, 0.7);
// }
// &::-webkit-scrollbar-corner {
// background: transparent;
// }
}

View file

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import s0 from './Rule.module.scss'; import s0 from './Rule.module.css';
const colorMap = { const colorMap = {
_default: '#59caf9', _default: '#59caf9',
@ -26,9 +26,7 @@ function Rule({ type, payload, proxy, id }) {
<div className={s0.b}>{payload}</div> <div className={s0.b}>{payload}</div>
<div className={s0.a}> <div className={s0.a}>
<div className={s0.type}>{type}</div> <div className={s0.type}>{type}</div>
<div className={s0.proxy} style={styleProxy}> <div style={styleProxy}>{proxy}</div>
{proxy}
</div>
</div> </div>
</div> </div>
</div> </div>

View file

@ -15,7 +15,6 @@
display: flex; display: flex;
align-items: center; align-items: center;
font-size: 12px; font-size: 12px;
opacity: 0.8; opacity: 0.8;
} }
@ -28,11 +27,3 @@
.type { .type {
width: 110px; width: 110px;
} }
.proxy {
// background: #f5bc41;
// background: #eee;
// color: #eee;
// padding: 5px;
// border-radius: 5px;
}

View file

@ -10,7 +10,7 @@ import useRemainingViewPortHeight from '../hooks/useRemainingViewPortHeight';
import { getRules, fetchRules, fetchRulesOnce } from 'd/rules'; import { getRules, fetchRules, fetchRulesOnce } from 'd/rules';
import s0 from './Rules.module.scss'; import s0 from './Rules.module.css';
const paddingBottom = 30; const paddingBottom = 30;
const mapStateToProps = s => ({ const mapStateToProps = s => ({

View file

@ -6,7 +6,7 @@ import { useActions, useStoreState } from 'm/store';
import debounce from 'lodash-es/debounce'; import debounce from 'lodash-es/debounce';
import s0 from './Search.module.scss'; import s0 from './Search.module.css';
function getSerachComponent({ mapStateToProps, actions }) { function getSerachComponent({ mapStateToProps, actions }) {
return memo(function RuleSearch() { return memo(function RuleSearch() {

View file

@ -1,9 +1,5 @@
.RuleSearch { .RuleSearch {
// width: 100%;
// padding: 0 40px;
// height: 40px;
padding: 0 40px 5px; padding: 0 40px 5px;
// height: 40px;
} }
.RuleSearchContainer { .RuleSearchContainer {

View file

@ -17,7 +17,7 @@ import SvgCommand from './SvgCommand';
import SvgSettings from './SvgSettings'; import SvgSettings from './SvgSettings';
import SvgFile from './SvgFile'; import SvgFile from './SvgFile';
import s from 'c/SideBar.module.scss'; import s from 'c/SideBar.module.css';
const icons = { const icons = {
activity: SvgActivity, activity: SvgActivity,

View file

@ -45,7 +45,7 @@
} }
} }
// a router link /* a router link */
.row { .row {
color: var(--color-text); color: var(--color-text);
text-decoration: none; text-decoration: none;
@ -56,7 +56,6 @@
@media (max-width: 768px) { @media (max-width: 768px) {
flex-direction: column; flex-direction: column;
// display: flex;
} }
svg { svg {
@ -82,7 +81,7 @@
} }
.themeSwitchContainer { .themeSwitchContainer {
$sz: 50px; --sz: 50px;
@media (max-width: 768px) { @media (max-width: 768px) {
display: none; display: none;
@ -92,8 +91,8 @@
bottom: 0; bottom: 0;
left: 50%; left: 50%;
transform: translateX(-50%); transform: translateX(-50%);
width: $sz; width: var(--sz);
height: $sz; height: var(--sz);
padding: 20px 0; padding: 20px 0;
display: flex; display: flex;
justify-content: center; justify-content: center;

View file

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import s0 from 'c/Switch.module.scss'; import s0 from 'c/Switch.module.css';
const noop = () => {}; const noop = () => {};
function Switch({ checked = false, onChange = noop, name = '' }) { function Switch({ checked = false, onChange = noop, name = '' }) {

View file

@ -1,17 +1,16 @@
// steal from https://codepen.io/joshnh/pen/hjbuH /* steal from https://codepen.io/joshnh/pen/hjbuH */
$white: #fff;
// $green: #53d76a;
$grey: #d3d3d3;
$color-theme: #047aff;
input.switch[type='checkbox'] { input.switch[type='checkbox'] {
--white: #fff;
--grey: #d3d3d3;
--color-theme: #047aff;
appearance: none; appearance: none;
outline: none; outline: none;
background-color: darken($white, 2%); background-color: darken(var(--white), 2%);
border: 1px solid $grey; border: 1px solid var(--grey);
border-radius: 26px; border-radius: 26px;
box-shadow: inset 0 0 0 1px $grey; box-shadow: inset 0 0 0 1px var(--grey);
cursor: pointer; cursor: pointer;
height: 28px; height: 28px;
position: relative; position: relative;
@ -20,8 +19,8 @@ input.switch[type='checkbox'] {
vertical-align: top; vertical-align: top;
&:after { &:after {
background-color: $white; background-color: var(--white);
border: 1px solid $grey; border: 1px solid var(--grey);
border-radius: 24px; border-radius: 24px;
box-shadow: inset 0 -3px 3px hsla(0, 0%, 0%, 0.025), box-shadow: inset 0 -3px 3px hsla(0, 0%, 0%, 0.025),
0 1px 4px hsla(0, 0%, 0%, 0.15), 0 4px 4px hsla(0, 0%, 0%, 0.1); 0 1px 4px hsla(0, 0%, 0%, 0.15), 0 4px 4px hsla(0, 0%, 0%, 0.1);
@ -35,13 +34,13 @@ input.switch[type='checkbox'] {
transition: border 0.25s 0.15s, left 0.25s 0.1s, right 0.15s 0.175s; transition: border 0.25s 0.15s, left 0.25s 0.1s, right 0.15s 0.175s;
} }
&:checked { &:checked {
border-color: $color-theme; border-color: var(--color-theme);
box-shadow: inset 0 0 0 13px $color-theme; box-shadow: inset 0 0 0 13px var(--color-theme);
padding-left: 18px; padding-left: 18px;
transition: border 0.25s, box-shadow 0.25s, padding 0.25s 0.15s; transition: border 0.25s, box-shadow 0.25s, padding 0.25s 0.15s;
&:after { &:after {
border-color: $color-theme; border-color: var(--color-theme);
left: 16px; left: 16px;
right: 0; right: 0;
transition: border 0.25s, left 0.15s 0.25s, right 0.25s 0.175s; transition: border 0.25s, left 0.15s 0.25s, right 0.25s 0.175s;

View file

@ -1,7 +1,7 @@
import React, { useMemo } from 'react'; import React, { useMemo } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import s0 from 'c/ToggleSwitch.module.scss'; import s0 from 'c/ToggleSwitch.module.css';
function ToggleSwitch({ options, value, name, onChange }) { function ToggleSwitch({ options, value, name, onChange }) {
const idxSelected = useMemo(() => options.map(o => o.value).indexOf(value), [ const idxSelected = useMemo(() => options.map(o => o.value).indexOf(value), [

View file

@ -5,7 +5,7 @@ import { useStoreState } from 'm/store';
import { getClashAPIConfig } from 'd/app'; import { getClashAPIConfig } from 'd/app';
import { fetchData } from '../api/traffic'; import { fetchData } from '../api/traffic';
import s0 from 'c/TrafficNow.module.scss'; import s0 from 'c/TrafficNow.module.css';
export default function TrafficNow() { export default function TrafficNow() {
const { upStr, downStr } = useSpeed(); const { upStr, downStr } = useSpeed();
@ -26,20 +26,17 @@ export default function TrafficNow() {
function useSpeed() { function useSpeed() {
const [speed, setSpeed] = useState({ upStr: '0 B/s', downStr: '0 B/s' }); const [speed, setSpeed] = useState({ upStr: '0 B/s', downStr: '0 B/s' });
const { hostname, port, secret } = useStoreState(getClashAPIConfig); const { hostname, port, secret } = useStoreState(getClashAPIConfig);
useEffect( useEffect(() => {
() => { return fetchData({
return fetchData({ hostname,
hostname, port,
port, secret
secret }).subscribe(o =>
}).subscribe(o => setSpeed({
setSpeed({ upStr: prettyBytes(o.up) + '/s',
upStr: prettyBytes(o.up) + '/s', downStr: prettyBytes(o.down) + '/s'
downStr: prettyBytes(o.down) + '/s' })
}) );
); }, [hostname, port, secret]);
},
[hostname, port, secret]
);
return speed; return speed;
} }

View file

@ -2,7 +2,6 @@
const path = require('path'); const path = require('path');
const webpack = require('webpack'); const webpack = require('webpack');
// const { rules } = require('./webpack.common');
const TerserPlugin = require('terser-webpack-plugin'); const TerserPlugin = require('terser-webpack-plugin');
const CopyPlugin = require('copy-webpack-plugin'); const CopyPlugin = require('copy-webpack-plugin');
const CleanPlugin = require('clean-webpack-plugin'); const CleanPlugin = require('clean-webpack-plugin');
@ -96,11 +95,15 @@ const loaders = {
postcss: { postcss: {
loader: 'postcss-loader', loader: 'postcss-loader',
options: { options: {
plugins: () => [require('autoprefixer'), require('cssnano')()] plugins: () =>
[
require('postcss-import')(),
require('postcss-nested')(),
require('autoprefixer')(),
require('postcss-extend-rule')(),
isDev ? false : require('cssnano')()
].filter(Boolean)
} }
},
sass: {
loader: 'sass-loader'
} }
}; };
@ -123,27 +126,6 @@ const rulesCssModules = {
].filter(Boolean) ].filter(Boolean)
}; };
const rulesSassModules = {
test: /\.module\.scss$/,
use: [
isDev ? loaders.style : MiniCssExtractPlugin.loader,
loaders.cssModule,
loaders.postcss,
loaders.sass
].filter(Boolean)
};
const rulesSass = {
test: /\.scss$/,
exclude: /\.module\.scss$/,
use: [
isDev ? loaders.style : MiniCssExtractPlugin.loader,
loaders.css,
loaders.postcss,
loaders.sass
].filter(Boolean)
};
const cssExtractPlugin = new MiniCssExtractPlugin({ const cssExtractPlugin = new MiniCssExtractPlugin({
filename: isDev ? '[name].bundle.css' : '[name].[chunkhash].css' filename: isDev ? '[name].bundle.css' : '[name].[chunkhash].css'
}); });
@ -202,9 +184,7 @@ module.exports = {
] ]
}, },
rulesCss, rulesCss,
rulesCssModules, rulesCssModules
rulesSass,
rulesSassModules
] ]
}, },
optimization: { optimization: {

864
yarn.lock

File diff suppressed because it is too large Load diff