Skip to content

Commit

Permalink
Chore/lint react styles (patternfly#3723)
Browse files Browse the repository at this point in the history
* 1 remaining linter error

* updated eslintignore to exclude css

* resolved PR feedback

* reverted emotionCss exported type
  • Loading branch information
evwilkin authored Feb 17, 2020
1 parent bf42d38 commit 0d5b8dc
Show file tree
Hide file tree
Showing 17 changed files with 180 additions and 13 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ coverage
.tmp
**/Generated
**/build
css

# package managers
yarn-error.log
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@
"generate": "yarn plop",
"lint:md": "yarn eslint packages/patternfly-4 --ext md --no-eslintrc --config .eslintrc-md.json --cache",
"lint:style": "stylelint \"**/sass/**/*.scss\" \"!**/dist/**/*.scss\"",
"lint:ts": "node --max-old-space-size=4096 node_modules/.bin/eslint packages/patternfly-4/react-core packages/patternfly-4/react-table packages/patternfly-4/react-topology packages/patternfly-4/react-catalog-view-extension packages/patternfly-4/react-docs packages/patternfly-4/react-inline-edit-extension packages/patternfly-4/react-charts packages/patternfly-4/react-integration packages/patternfly-4/react-styled-system --ext js,jsx,ts,tsx --cache",
"lint:ts": "node --max-old-space-size=4096 node_modules/.bin/eslint packages/patternfly-4/react-core packages/patternfly-4/react-table packages/patternfly-4/react-topology packages/patternfly-4/react-catalog-view-extension packages/patternfly-4/react-docs packages/patternfly-4/react-inline-edit-extension packages/patternfly-4/react-charts packages/patternfly-4/react-integration packages/patternfly-4/react-styled-system packages/patternfly-4/react-styles --ext js,jsx,ts,tsx --cache",
"lint:versions": "node ./packages/patternfly-4/verifyCoreVersions.js",
"prettier": "node node_modules/.bin/prettier --write \"storybook/**/*.{js,ts,tsx}\" \"packages/**/*.{js,ts,tsx}\" \"scripts/**/*.{js,ts,tsx}\"",
"serve:docs": "lerna run serve",
Expand Down
5 changes: 5 additions & 0 deletions packages/patternfly-4/react-styles/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"rules": {
"camelcase": "off"
}
}
1 change: 0 additions & 1 deletion packages/patternfly-4/react-styles/scripts/copyStyles.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable no-case-declarations */
const { copySync } = require('fs-extra');
const { resolve, dirname, join } = require('path');

Expand Down
1 change: 1 addition & 0 deletions packages/patternfly-4/react-styles/src/StyleSheet.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { StyleDeclarationStatic } from './utils';
import { Interpolation } from 'emotion';
import { ClassNameArg } from 'create-emotion';

// eslint-disable-next-line @typescript-eslint/array-type
type emotionCss = (...classNames: Array<ClassNameArg | StyleDeclarationStatic>) => string;

export interface StyleSheetStatic {
Expand Down
3 changes: 3 additions & 0 deletions packages/patternfly-4/react-styles/src/StyleSheet.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ export const StyleSheet = {
}
};

/**
* @param {Array} styles - Array of styles
*/
export function css(...styles) {
const filteredStyles = [];
styles.forEach(style => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ const properties = [
'grid-template-rows'
];

/**
* @param {any} key - Key
*/
function createOverride(key) {
return {
set(v) {
Expand All @@ -35,6 +38,9 @@ function createOverride(key) {
};
}

/**
*
*/
export function addOverrides() {
const overrides = properties.reduce(
(acc, property) => ({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
/* eslint-disable jsdoc/require-param-description, jsdoc/require-param-type */
import * as css from 'css';
import * as jsdom from 'jsdom';

const { JSDOM } = jsdom;

function getSelectors(nodes) {
return nodes.reduce((selectors, node) => {
const props = typeof node.props === 'function' ? node.props() : node.props;
return [...selectors, getSelectorsFromProps(props)];
}, []);
}

/**
* @param props
*/
function getSelectorsFromProps(props = {}) {
const className = props.className || props.class;
if (className) {
Expand All @@ -21,15 +18,37 @@ function getSelectorsFromProps(props = {}) {
return [];
}

/**
* @param nodes
*/
function getSelectors(nodes) {
return nodes.reduce((selectors, node) => {
const props = typeof node.props === 'function' ? node.props() : node.props;
return [...selectors, getSelectorsFromProps(props)];
}, []);
}

/**
* @param c
*/
function componentToHex(c) {
const hex = c.toString(16);
return hex.length === 1 ? `0${hex}` : hex;
}

/**
* @param r
* @param g
* @param b
*/
function rgbToHex(r, g, b) {
return `#${componentToHex(r)}${componentToHex(g)}${componentToHex(b)}`;
}

/**
* @param classNames
* @param cssStr
*/
function getComputedStyles(classNames, cssStr) {
const dom = new JSDOM(
`<!DOCTYPE html>
Expand All @@ -39,16 +58,20 @@ function getComputedStyles(classNames, cssStr) {
);
const cs = dom.window.getComputedStyle(dom.window.document.body.children[0]);
const values = {};
for (let i = 0; i < cs.length; i++) {
const key = cs[i];
for (const key of cs.length) {
const value = cs
.getPropertyValue(key)
// eslint-disable-next-line radix
.replace(/rgb\(([\d|,|\s]+)\)/g, (full, match) => rgbToHex(...match.split(',').map(n => parseInt(n, 10))));
values[key] = value;
}
return values;
}

/**
* @param bufferedStyles
* @param globalCSS
*/
function getStylesAST(bufferedStyles, globalCSS = '') {
const ast = css.parse(`${globalCSS}\n${bufferedStyles}`);
const vars = {};
Expand All @@ -71,6 +94,10 @@ function getStylesAST(bufferedStyles, globalCSS = '') {
return ast;
}

/**
* @param nodeSelectors
* @param computedStyles
*/
function formatComputedStyles(nodeSelectors, computedStyles) {
const selector = nodeSelectors.join('');
const cssString = `${selector} {
Expand All @@ -81,6 +108,11 @@ function formatComputedStyles(nodeSelectors, computedStyles) {
return css.stringify(css.parse(cssString));
}

/**
* @param nodeSelectors
* @param insertedStyles
* @param globalCSS
*/
function getStyles(nodeSelectors, insertedStyles, globalCSS) {
if (!nodeSelectors.length) {
return '';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/**
* @param {any} node - Node
* @param {Array} nodes - array of nodes
*/
function getNodes(node, nodes = []) {
if (node.children) {
const children = typeof node.children === 'function' ? node.children() : node.children;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,23 @@ import { getNodes } from './reactUtils';
import { getInsertedStyles } from '../../../utils';
import { addOverrides } from './cssPropertyOverrides';

/**
*
*/
export function createSerializer({ globalCSS = '' } = {}) {
addOverrides();
/**
* @param {any} val - Value to test
*/
function test(val) {
// eslint-disable-next-line no-undef
return val && !val.withStyles && val.$$typeof === Symbol.for('react.test.json');
}

/**
* @param {any} val - Value
* @param {Function} printer - Printer function
*/
function print(val, printer) {
const nodes = getNodes(val);
nodes.forEach(node => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import createCacheKeyFunction from 'fbjs-scripts/jest/createCacheKeyFunction';

import { minifyCSS, cssToJS } from '../util';

/**
* @param {string} src - Src string
*/
export function process(src) {
return cssToJS(minifyCSS(src), false);
}
Expand Down
4 changes: 4 additions & 0 deletions packages/patternfly-4/react-styles/src/build/loader/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { cssToJSNew } from '../util';

/**
* @param {string} source - Source
* @param {string} cssOutputPath - CSS output path
*/
export default function pfStyleLoader(source, cssOutputPath) {
return cssToJSNew(source, cssOutputPath, false);
}
44 changes: 44 additions & 0 deletions packages/patternfly-4/react-styles/src/build/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ import { getCSSClasses, isModifier, formatClassName } from '../utils';
export const packageName = '@patternfly/react-styles';
export const styleSheetToken = 'StyleSheet';

/**
* @param {string} cssString - CSS string
* @param {string} cssOutputPath - CSS output path
* @param {boolean} useModules - Boolean
*/
export function cssToJS(cssString, cssOutputPath = '', useModules = false) {
let cssRequire = '';
let cssImport = '';
Expand All @@ -30,6 +35,11 @@ module.exports = ${styleSheetToken}.parse(\`${cssString}\`);
`;
}

/**
* @param {string} cssString - CSS string
* @param {string} cssOutputPath - CSS output path
* @param {boolean} useModules - Boolean
*/
export function cssToJSNew(cssString, cssOutputPath = '', useModules = false) {
let cssRequire = '';
let cssImport = '';
Expand All @@ -39,6 +49,7 @@ export function cssToJSNew(cssString, cssOutputPath = '', useModules = false) {
}

const cssClasses = getCSSClasses(cssString);
// eslint-disable-next-line no-undef
const distinctValues = [...new Set(cssClasses)];
const classDeclaration = [];
const modifiersDeclaration = [];
Expand Down Expand Up @@ -78,43 +89,76 @@ module.exports = {
`;
}

/**
* @param {string | number | Buffer | URL} pathToCSSFile - CSS file path
*/
export function getFullCSS(pathToCSSFile) {
const rawCss = readFileSync(pathToCSSFile, 'utf8').replace('@charset "UTF-8";', '');
return rawCss;
}

/**
* @param {string | number | Buffer | URL} pathToCSSFile - CSS file path
*/
export function getCSS(pathToCSSFile) {
const rawCss = readFileSync(pathToCSSFile, 'utf8').replace('@charset "UTF-8";', '');
// eslint-disable-next-line @typescript-eslint/no-use-before-define
return minifyCSS(rawCss);
}

/**
* @param {string} cssString - CSS string
*/
export function minifyCSS(cssString) {
return css.stringify(css.parse(cssString.replace('@charset "UTF-8";', '')), {
compress: true
});
}

/**
* @param {any} destinationPath - Path to destination
* @param {any} contents - Contents
*/
export function writeCSSFile(destinationPath, contents) {
ensureDir(path.dirname(destinationPath)).then(() => {
const replacementString = contents.replace(/..\/..\/assets/g, '../../../../../styles/assets');
outputFileSync(destinationPath, replacementString);
});
}

/**
* @param {any} rootPath - Root path
* @param {any} originalPath - Original path
* @param {any} destinationPath - Path to destination
* @param {any} contents - Contents
*/
export function writeCSSJSFile(rootPath, originalPath, destinationPath, contents) {
outputFileSync(destinationPath, contents);
}

/**
* @param {any} from - From
* @param {any} to - To
*/
export function getRelativeImportPath(from, to) {
const parsedTo = path.parse(to);
const newImportPath = path.normalize(path.join(relative(from, parsedTo.dir), parsedTo.base));
return newImportPath.startsWith('.') ? newImportPath : `./${newImportPath}`;
}

/**
* @param {any} outDir - Output directory
* @param {any} rootPath - Root path
* @param {string | number | Buffer | URL} pathToCSSFile - CSS file path
*/
export function getCSSOutputPath(outDir, rootPath, pathToCSSFile) {
// eslint-disable-next-line @typescript-eslint/no-use-before-define
return path.join(path.resolve(rootPath, outDir), getFormattedCSSOutputPath(pathToCSSFile));
}

/**
* @param {string | number | Buffer | URL} pathToCSSFile - CSS file path
*/
function getFormattedCSSOutputPath(pathToCSSFile) {
const { dir, name } = path.parse(pathToCSSFile);
let formattedDir = dir;
Expand Down
22 changes: 21 additions & 1 deletion packages/patternfly-4/react-styles/src/generateClasses.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable global-require,import/no-dynamic-require */
const camelcase = require('camel-case');

const glob = require('glob');
Expand Down Expand Up @@ -38,8 +37,13 @@ inlineCssFiles.forEach(filePath => {
outputFileSync(cssOutputPath.replace('.css', '.ts'), newClass);
});

/**
* @param {string} cssString - CSS string
* @param {string} cssOutputPath - Path string
*/
function cssToJSNew(cssString, cssOutputPath = '') {
const cssClasses = getCSSClasses(cssString);
// eslint-disable-next-line no-undef
const distinctValues = [...new Set(cssClasses)];
const classDeclaration = [];
const modifiersDeclaration = [];
Expand All @@ -65,22 +69,38 @@ export default {
}`;
}

/**
* @param {string} cssString - CSS string
*/
function getCSSClasses(cssString) {
return cssString.match(/(\.)(?!\d)([^\s\.,{\[>+~#:)]*)(?![^{]*})/g); //eslint-disable-line
}

/**
* @param {string} className - Class name
*/
function formatClassName(className) {
return camelcase(className.replace(/pf-((c|l|m|u|is|has)-)?/g, ''));
}

/**
* @param {string} className - Class name
*/
function isModifier(className) {
return Boolean(className && className.startsWith) && className.startsWith('.pf-m-');
}

/**
* @param {any} absFilePath - Absolute file path
* @param {any} pathToCSSFile - Path to CSS file
*/
function getCSSOutputPath(absFilePath, pathToCSSFile) {
return join(absFilePath, getFormattedCSSOutputPath(pathToCSSFile));
}

/**
* @param {any} pathToCSSFile - Path to CSS file
*/
function getFormattedCSSOutputPath(pathToCSSFile) {
const { dir, name } = parse(pathToCSSFile);
let formattedDir = dir;
Expand Down
1 change: 0 additions & 1 deletion packages/patternfly-4/react-styles/src/removeTS.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable global-require,import/no-dynamic-require */
const glob = require('glob');
const fs = require('fs');

Expand Down
Loading

0 comments on commit 0d5b8dc

Please sign in to comment.