Skip to content

Commit

Permalink
Feat: add className={styles.xxx} automatic completion (#1002)
Browse files Browse the repository at this point in the history
* feat: init

* Fix `style={styles.xxx}` automatic completion failed with nested css file (#1004)

* feat: init

* feat: upadte
  • Loading branch information
fyangstudio authored Apr 18, 2022
1 parent b0c27f9 commit 97e47aa
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 6 deletions.
4 changes: 4 additions & 0 deletions extensions/style-helper/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Change Log

## 1.1.1
- feat: add `className={styles.xxx}` automatic completion will be provided when editing css file
- fix: `style={styles.xxx}` automatic completion failed with nested css file

## 1.1.0
- feat: add `className={}` completion item
- feat: add `styles` completion item and auto import module style file
Expand Down
2 changes: 1 addition & 1 deletion extensions/style-helper/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"displayName": "React Style Helper",
"description": "Easily write styles(CSS/LESS/SASS).",
"publisher": "iceworks-team",
"version": "1.1.0",
"version": "1.1.1",
"engines": {
"vscode": "^1.41.0"
},
Expand Down
19 changes: 17 additions & 2 deletions extensions/style-helper/src/cssClassAutoCompete/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ function provideCompletionItems(document: vscode.TextDocument, position: vscode.
fs.readdirSync(directory).forEach((file) => {
if (path.extname(file) === '.jsx' || path.extname(file) === '.tsx') {
const filePath = `${directory}/${file}`;
// Add className="xxx" and style={styles.xxx}
classNames = classNames.concat(getClassNames(filePath), getCSSModuleKeys(filePath));
// Add className="xxx" , className={styles.xxx} and style={styles.xxx}
classNames = classNames.concat(getClassNames(filePath), getCSSModuleClassNames(filePath), getCSSModuleKeys(filePath));
}
});
if (classNames.length) {
Expand Down Expand Up @@ -59,6 +59,21 @@ function getClassNames(filePath: string): string[] {
return classNames;
}

// Process className={styles.xxx}
function getCSSModuleClassNames(filePath: string): string[] {
const code = fs.readFileSync(filePath, 'utf8');
const reg = new RegExp('className=\\{styles\\.([\\w\\.]+)\\}', 'g');

const CSSModuleClassNames: string[] = [];
let matched: RegExpExecArray | null;

// eslint-disable-next-line
while ((matched = reg.exec(code)) !== null) {
CSSModuleClassNames.push(matched[1]);
}
return CSSModuleClassNames;
}

// Process style={styles.xxx}
function getCSSModuleKeys(filePath: string): string[] {
const code = fs.readFileSync(filePath, 'utf8');
Expand Down
39 changes: 36 additions & 3 deletions extensions/style-helper/src/styleInfoViewer/findStyleSelectors.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as fs from 'fs';
import * as path from 'path';
import css from 'css';
import * as css from 'css';
import flatten from 'css-flatten';
import { IStyle } from './findStyle';
import { IStyleDependency } from './findStyleDependencies';

Expand All @@ -10,12 +11,44 @@ export default function findStyleSelectors(directory: string, styleDependencies:

for (let i = 0, l = styleDependencies.length; i < l; i++) {
const file = path.join(directory, styleDependencies[i].source);
const { stylesheet } = css.parse(fs.readFileSync(file, 'utf-8'));

const fileContent = fs.readFileSync(file, 'utf-8');
let cssContent = fileContent;

// Remove media and keyframes, it will cause css.parse error
cssContent = cssContent.replace(/@[media|keyframes][^{]+\{([\s\S]+?})\s*}/g, '');

if (
// Flattens nested SASS LESS string
/s(c|a)ss$|\.less$/.test(file)
) {
// https://www.npmjs.com/package/css-flatten
// Before:
// .foo {
// color: red;
// .bar {
// color: blue;
// }
// }
// After:
// .foo {
// color: red;
// }
// .foo .bar {
// color: blue;
// }
cssContent = flatten(cssContent);
}

const { stylesheet } = css.parse(cssContent);

// eslint-disable-next-line
stylesheet.rules.forEach((rule: IStyle) => {
if (rule.selectors) {
selectors = selectors.concat(rule.selectors);
selectors = selectors.concat(rule.selectors.map((selector) => {
// .foo .bar => .bar
return selector.split(' ').pop() || '';
}));
}
});
}
Expand Down

0 comments on commit 97e47aa

Please sign in to comment.