livestylesync-vite-plugin 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,8 @@
1
+ import { Plugin } from 'vite';
2
+
3
+ interface LiveStyleSyncOptions {
4
+ port?: number;
5
+ }
6
+ declare function liveStyleSync(options?: LiveStyleSyncOptions): Plugin;
7
+
8
+ export { liveStyleSync };
package/dist/index.js ADDED
@@ -0,0 +1,78 @@
1
+ // src/index.ts
2
+ import { WebSocketServer } from "ws";
3
+ import { readFileSync, writeFileSync } from "fs";
4
+ function escapeForRegex(s) {
5
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
6
+ }
7
+ function selectorToRegex(selector) {
8
+ return selector.split(",").map((s) => escapeForRegex(s.trim())).join(",\\s*\\n?\\s*");
9
+ }
10
+ function findBlock(css, selRegex) {
11
+ const pattern = new RegExp(`${selRegex}\\s*\\{`, "s");
12
+ const match = pattern.exec(css);
13
+ if (!match) return null;
14
+ const start = match.index + match[0].length - 1;
15
+ let depth = 0;
16
+ for (let i = start; i < css.length; i++) {
17
+ if (css[i] === "{") depth++;
18
+ else if (css[i] === "}") {
19
+ depth--;
20
+ if (depth === 0) return { start, end: i };
21
+ }
22
+ }
23
+ return null;
24
+ }
25
+ function camelToKebab(prop) {
26
+ return prop.replace(/([A-Z])/g, "-$1").toLowerCase();
27
+ }
28
+ function patchCss(filePath, selector, prop, value) {
29
+ const cssProp = camelToKebab(prop);
30
+ const css = readFileSync(filePath, "utf-8");
31
+ const selRegex = selectorToRegex(selector);
32
+ const block = findBlock(css, selRegex);
33
+ if (!block) {
34
+ console.log("[LSS] selector not found, skipping");
35
+ return;
36
+ }
37
+ const blockContent = css.slice(block.start + 1, block.end);
38
+ const propPattern = new RegExp(`${cssProp}\\s*:[^;]+;`);
39
+ let newBlockContent;
40
+ if (propPattern.test(blockContent)) {
41
+ newBlockContent = blockContent.replace(propPattern, `${cssProp}: ${value};`);
42
+ } else {
43
+ newBlockContent = blockContent.trimEnd() + `
44
+ ${cssProp}: ${value};
45
+ `;
46
+ }
47
+ const updated = css.slice(0, block.start + 1) + newBlockContent + css.slice(block.end);
48
+ writeFileSync(filePath, updated, "utf-8");
49
+ console.log(`[LSS] wrote ${cssProp}: ${value} \u2192 ${filePath}`);
50
+ }
51
+ function liveStyleSync(options = {}) {
52
+ const port = options.port ?? 3100;
53
+ return {
54
+ name: "livestylesync",
55
+ configureServer(server) {
56
+ const wss = new WebSocketServer({ port });
57
+ wss.on("error", (err) => {
58
+ if (err.code !== "EADDRINUSE") throw err;
59
+ console.log(`[LSS] port ${port} busy \u2014 restart Vite to reconnect`);
60
+ });
61
+ server.httpServer?.once("close", () => wss.close());
62
+ wss.on("connection", (socket) => {
63
+ console.log("[LSS] client connected");
64
+ socket.on("message", (raw) => {
65
+ const msg = JSON.parse(raw.toString());
66
+ if (!msg.fileUrl || !msg.selector || !msg.prop || !msg.value) return;
67
+ patchCss(msg.fileUrl, msg.selector, msg.prop, msg.value);
68
+ });
69
+ socket.on("close", () => {
70
+ console.log("[LSS] client disconnected");
71
+ });
72
+ });
73
+ }
74
+ };
75
+ }
76
+ export {
77
+ liveStyleSync
78
+ };
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "livestylesync-vite-plugin",
3
+ "version": "0.1.0",
4
+ "description": "Vite plugin for LiveStyleSync",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.js",
12
+ "types": "./dist/index.d.ts"
13
+ }
14
+ },
15
+ "files": ["dist"],
16
+ "scripts": {
17
+ "build": "tsup src/index.ts --format esm --dts --external vite --external ws"
18
+ },
19
+ "peerDependencies": {
20
+ "vite": ">=4"
21
+ },
22
+ "dependencies": {
23
+ "ws": "^8.20.1"
24
+ },
25
+ "devDependencies": {
26
+ "@types/node": "^24.12.2",
27
+ "@types/ws": "^8.18.1",
28
+ "tsup": "^8.5.1",
29
+ "typescript": "^6.0.3",
30
+ "vite": "^8.0.11"
31
+ }
32
+ }