Skip to content

Commit e38a6e6

Browse files
committed
feat: support hot reload config file
1 parent 5bfe650 commit e38a6e6

4 files changed

Lines changed: 128 additions & 109 deletions

File tree

src/extension.ts

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,36 +4,36 @@ import { registerCodeFolding } from './lib/folding';
44
import { init } from './lib/core';
55
import { workspace } from 'vscode';
66
import type { Core } from './interfaces';
7-
import type { ExtensionContext } from 'vscode';
7+
import type { Disposable, ExtensionContext } from 'vscode';
88

99
let CORE: Core = { colors: {}, variantCompletions: [], staticCompletions: [], colorCompletions: [], dynamicCompletions: [] };
10+
let DISPOSABLES: Disposable[] = [];
1011

1112
export async function activate(ctx: ExtensionContext) {
1213

13-
CORE = await init();
1414
const fileSystemWatcher = workspace.createFileSystemWatcher('**/{tailwind,windi}.config.{js,cjs,ts}');
1515

16-
// Changes configuration should invalidate above cache
17-
fileSystemWatcher.onDidChange(async () => {
16+
const onUpdate = async () => {
1817
CORE = await init();
19-
});
18+
DISPOSABLES.forEach(i => i.dispose());
19+
DISPOSABLES = [...registerCompletions(ctx, CORE), ...registerCommands(ctx, CORE)];
20+
};
21+
22+
CORE = await init();
23+
registerCodeFolding(ctx);
24+
DISPOSABLES = [...registerCompletions(ctx, CORE), ...registerCommands(ctx, CORE)];
25+
26+
console.log('Windi CSS Intellisense is now active!');
27+
28+
// Changes configuration should invalidate above cache
29+
fileSystemWatcher.onDidChange(onUpdate);
2030

2131
// This handles the case where the project didn't have config file
2232
// but was created after VS Code was initialized
23-
fileSystemWatcher.onDidCreate(async () => {
24-
CORE = await init();
25-
});
33+
fileSystemWatcher.onDidCreate(onUpdate);
2634

2735
// If the config is deleted, utilities&variants should be regenerated
28-
fileSystemWatcher.onDidDelete(async () => {
29-
CORE = await init();
30-
});
31-
32-
registerCompletions(ctx, CORE);
33-
registerCodeFolding(ctx);
34-
registerCommands(ctx, CORE);
35-
36-
console.log('Windi CSS Intellisense is now active!');
36+
fileSystemWatcher.onDidDelete(onUpdate);
3737
}
3838

3939
// eslint-disable-next-line @typescript-eslint/no-empty-function

src/lib/commands.ts

Lines changed: 105 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -4,98 +4,116 @@ import { writeFileSync } from 'fs';
44
import { dirname, join } from 'path';
55
import { StyleSheet } from 'windicss/utils/style';
66
import { workspace } from 'vscode';
7+
import { getConfig, sortClassNames, toggleConfig } from '../utils';
78
import type { ExtensionContext } from 'vscode';
89
import type { Core } from '../interfaces';
9-
import { getConfig, sortClassNames, toggleConfig } from '../utils';
10+
import type { Disposable } from 'vscode';
11+
12+
let DISPOSABLES: Disposable[] = [];
13+
14+
export function registerCommands(ctx: ExtensionContext, core: Core): Disposable[] {
15+
function createDisposables() {
16+
const disposables: Disposable[] = [];
17+
disposables.push(
18+
commands.registerTextEditorCommand('windicss.interpret', (textEditor, textEdit) => {
19+
if (!core.processor) return;
20+
const text = textEditor.document.getText();
21+
const parser = new HTMLParser(text);
22+
const preflights = core.processor.preflight(text);
23+
const utilities = core.processor.interpret(parser.parseClasses().map(i => i.result).join(' ')).styleSheet;
24+
writeFileSync(join(dirname(textEditor.document.uri.fsPath), 'windi.css'), [preflights.build(), utilities.build()].join('\n'));
25+
})
26+
);
27+
28+
disposables.push(
29+
commands.registerTextEditorCommand('windicss.compile', (textEditor, textEdit) => {
30+
if (!core.processor) return;
31+
const text = textEditor.document.getText();
32+
const parser = new HTMLParser(text);
33+
const preflights = core.processor.preflight(text);
34+
const outputHTML: string[] = [];
35+
const outputCSS: StyleSheet[] = [];
36+
37+
let indexStart = 0;
38+
39+
for (const p of parser.parseClasses()) {
40+
outputHTML.push(text.substring(indexStart, p.start));
41+
const result = core.processor.compile(p.result, 'windi-', true);
42+
outputCSS.push(result.styleSheet);
43+
outputHTML.push([result.className, ...result.ignored].join(' '));
44+
indexStart = p.end;
45+
}
46+
outputHTML.push(text.substring(indexStart));
47+
48+
const utilities = outputCSS.reduce((previousValue, currentValue) => previousValue.extend(currentValue), new StyleSheet()).combine();
49+
textEdit.replace(new Range(new Position(0, 0), textEditor.document.lineAt(textEditor.document.lineCount-1).range.end), outputHTML.join(''));
50+
writeFileSync(join(dirname(textEditor.document.uri.fsPath), 'windi.css'), [preflights.build(), utilities.build()].join('\n'));
51+
})
52+
);
53+
54+
disposables.push(
55+
commands.registerTextEditorCommand('windicss.sort', (textEditor, textEdit) => {
56+
const text = textEditor.document.getText();
57+
const parser = new HTMLParser(text);
58+
59+
const classes = parser.parseClasses();
60+
const variants = Object.keys(core.processor?.resolveVariants() ?? {});
61+
const variantsMap = Object.assign({}, ...variants.map((value, index) => ({ [value]: index + 1 })));
62+
63+
for (const p of classes) {
64+
const sortedP = sortClassNames(p.result, variantsMap);
65+
textEdit.replace(new Range(textEditor.document.positionAt(p.start), textEditor.document.positionAt(p.end)), sortedP);
66+
}
67+
})
68+
);
69+
70+
// if runOnSave is enabled in settings, trigger command on file save
71+
if(getConfig('windicss.sortOnSave')) {
72+
disposables.push(
73+
workspace.onWillSaveTextDocument((_e) => {
74+
commands.executeCommand('windicss.sort');
75+
})
76+
);
77+
}
78+
79+
disposables.push(
80+
commands.registerCommand('windicss.toggle-folding', () => toggleConfig('windicss.enableCodeFolding'))
81+
);
82+
83+
disposables.push(
84+
commands.registerCommand('windicss.toggle-decorators', () => {
85+
toggleConfig('windicss.enableColorDecorators');
86+
})
87+
);
88+
89+
disposables.push(
90+
commands.registerCommand('windicss.toggle-preview', () => {
91+
toggleConfig('windicss.enableHoverPreview');
92+
})
93+
);
94+
95+
disposables.push(
96+
commands.registerCommand('windicss.toggle-completion', () => {
97+
toggleConfig('windicss.enableCodeCompletion');
98+
})
99+
);
10100

11-
export function registerCommands(ctx: ExtensionContext, core: Core): void {
12-
ctx.subscriptions.push(
13-
commands.registerTextEditorCommand('windicss.interpret', (textEditor, textEdit) => {
14-
if (!core.processor) return;
15-
const text = textEditor.document.getText();
16-
const parser = new HTMLParser(text);
17-
const preflights = core.processor.preflight(text);
18-
const utilities = core.processor.interpret(parser.parseClasses().map(i => i.result).join(' ')).styleSheet;
19-
writeFileSync(join(dirname(textEditor.document.uri.fsPath), 'windi.css'), [preflights.build(), utilities.build()].join('\n'));
20-
})
21-
);
22-
23-
ctx.subscriptions.push(
24-
commands.registerTextEditorCommand('windicss.compile', (textEditor, textEdit) => {
25-
if (!core.processor) return;
26-
const text = textEditor.document.getText();
27-
const parser = new HTMLParser(text);
28-
const preflights = core.processor.preflight(text);
29-
const outputHTML: string[] = [];
30-
const outputCSS: StyleSheet[] = [];
31-
32-
let indexStart = 0;
33-
34-
for (const p of parser.parseClasses()) {
35-
outputHTML.push(text.substring(indexStart, p.start));
36-
const result = core.processor.compile(p.result, 'windi-', true);
37-
outputCSS.push(result.styleSheet);
38-
outputHTML.push([result.className, ...result.ignored].join(' '));
39-
indexStart = p.end;
40-
}
41-
outputHTML.push(text.substring(indexStart));
42-
43-
const utilities = outputCSS.reduce((previousValue, currentValue) => previousValue.extend(currentValue), new StyleSheet()).combine();
44-
textEdit.replace(new Range(new Position(0, 0), textEditor.document.lineAt(textEditor.document.lineCount-1).range.end), outputHTML.join(''));
45-
writeFileSync(join(dirname(textEditor.document.uri.fsPath), 'windi.css'), [preflights.build(), utilities.build()].join('\n'));
46-
})
47-
);
48-
49-
ctx.subscriptions.push(
50-
commands.registerTextEditorCommand('windicss.sort', (textEditor, textEdit) => {
51-
const text = textEditor.document.getText();
52-
const parser = new HTMLParser(text);
53-
54-
const classes = parser.parseClasses();
55-
const variants = Object.keys(core.processor?.resolveVariants() ?? {});
56-
const variantsMap = Object.assign({}, ...variants.map((value, index) => ({ [value]: index + 1 })));
57-
58-
for (const p of classes) {
59-
const sortedP = sortClassNames(p.result, variantsMap);
60-
textEdit.replace(new Range(textEditor.document.positionAt(p.start), textEditor.document.positionAt(p.end)), sortedP);
61-
}
62-
})
63-
);
64-
65-
// if runOnSave is enabled in settings, trigger command on file save
66-
if(getConfig('windicss.sortOnSave')) {
67-
ctx.subscriptions.push(
68-
workspace.onWillSaveTextDocument((_e) => {
69-
commands.executeCommand('windicss.sort');
101+
disposables.push(
102+
commands.registerCommand('windicss.toggle-dynamic-completion', () => {
103+
toggleConfig('enableDynamicCompletion');
70104
})
71105
);
106+
107+
ctx.subscriptions.push(...DISPOSABLES);
108+
109+
return disposables;
72110
}
73111

74-
ctx.subscriptions.push(
75-
commands.registerCommand('windicss.toggle-folding', () => toggleConfig('windicss.enableCodeFolding'))
76-
);
77-
78-
ctx.subscriptions.push(
79-
commands.registerCommand('windicss.toggle-decorators', () => {
80-
toggleConfig('windicss.enableColorDecorators');
81-
})
82-
);
83-
84-
ctx.subscriptions.push(
85-
commands.registerCommand('windicss.toggle-preview', () => {
86-
toggleConfig('windicss.enableHoverPreview');
87-
})
88-
);
89-
90-
ctx.subscriptions.push(
91-
commands.registerCommand('windicss.toggle-completion', () => {
92-
toggleConfig('windicss.enableCodeCompletion');
93-
})
94-
);
95-
96-
ctx.subscriptions.push(
97-
commands.registerCommand('windicss.toggle-dynamic-completion', () => {
98-
toggleConfig('enableDynamicCompletion');
99-
})
100-
);
112+
workspace.onDidChangeConfiguration(() => {
113+
DISPOSABLES.forEach(i => i.dispose());
114+
DISPOSABLES = createDisposables() ?? [];
115+
}, null, ctx.subscriptions);
116+
117+
DISPOSABLES = createDisposables() ?? [];
118+
return DISPOSABLES;
101119
}

src/lib/completions.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@ import { HTMLParser } from '../utils/parser';
66
import type { Core } from '../interfaces';
77
import type { Disposable } from 'vscode';
88

9-
109
let DISPOSABLES: Disposable[] = [];
1110
const TRIGGERS = ['"', '\'', ' ', ':'];
1211

13-
export async function registerCompletions(ctx: ExtensionContext, core: Core): Promise<void> {
12+
export function registerCompletions(ctx: ExtensionContext, core: Core): Disposable[] {
1413
function createDisposables() {
1514
let disposables: Disposable[] = [];
1615
if (!getConfig('windicss.enableCodeCompletion')) return;
@@ -123,11 +122,11 @@ export async function registerCompletions(ctx: ExtensionContext, core: Core): Pr
123122
return disposables;
124123
}
125124

126-
DISPOSABLES.forEach(i => i.dispose());
127-
DISPOSABLES = createDisposables() ?? [];
128-
129125
workspace.onDidChangeConfiguration(() => {
130126
DISPOSABLES.forEach(i => i.dispose());
131127
DISPOSABLES = createDisposables() ?? [];
132128
}, null, ctx.subscriptions);
129+
130+
DISPOSABLES = createDisposables() ?? [];
131+
return DISPOSABLES;
133132
}

src/lib/core.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@ export async function init():Promise<Core> {
1515
configFile = files[0].fsPath;
1616
if (configFile.endsWith('.ts')) {
1717
registerTS();
18+
delete require.cache[require.resolve(configFile)];
1819
const mod = require(configFile);
1920
if (mod.default) config = mod.default;
2021
} else {
22+
delete require.cache[require.resolve(resolve(configFile))];
2123
config = require(resolve(configFile));
2224
}
2325
console.log(`Loading Config File: ${configFile}`);

0 commit comments

Comments
 (0)