boss-css 0.0.1 → 0.0.3

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.
Files changed (268) hide show
  1. package/README.md +1 -0
  2. package/dist/_virtual/rolldown_runtime.cjs +43 -0
  3. package/dist/_virtual/rolldown_runtime.mjs +20 -0
  4. package/dist/api/browser.cjs +54 -0
  5. package/dist/api/browser.mjs +48 -0
  6. package/dist/api/config.cjs +94 -0
  7. package/dist/api/config.mjs +91 -0
  8. package/dist/api/css.cjs +304 -0
  9. package/dist/api/css.mjs +303 -0
  10. package/dist/api/dictionary.cjs +218 -0
  11. package/dist/api/dictionary.mjs +215 -0
  12. package/dist/api/file/dts.cjs +21 -0
  13. package/dist/api/file/dts.mjs +21 -0
  14. package/dist/api/file/file.cjs +123 -0
  15. package/dist/api/file/file.mjs +120 -0
  16. package/dist/api/file/js.cjs +118 -0
  17. package/dist/api/file/js.mjs +116 -0
  18. package/dist/api/names.cjs +52 -0
  19. package/dist/api/names.mjs +46 -0
  20. package/dist/api/noopCss.cjs +37 -0
  21. package/dist/api/noopCss.mjs +36 -0
  22. package/dist/api/propTree.cjs +54 -0
  23. package/dist/api/propTree.mjs +48 -0
  24. package/dist/api/server.cjs +112 -0
  25. package/dist/api/server.mjs +106 -0
  26. package/dist/cli/build.cjs +1 -0
  27. package/dist/cli/build.mjs +3 -0
  28. package/dist/cli/index.cjs +30 -0
  29. package/dist/cli/index.mjs +29 -0
  30. package/dist/cli/tasks/build.cjs +24 -0
  31. package/dist/cli/tasks/build.mjs +23 -0
  32. package/dist/cli/tasks/choose.cjs +47 -0
  33. package/dist/cli/tasks/choose.mjs +46 -0
  34. package/dist/cli/tasks/compile.cjs +68 -0
  35. package/dist/cli/tasks/compile.mjs +67 -0
  36. package/dist/cli/tasks/dev.cjs +51 -0
  37. package/dist/cli/tasks/dev.mjs +48 -0
  38. package/dist/cli/tasks/init.cjs +1835 -0
  39. package/dist/cli/tasks/init.mjs +1831 -0
  40. package/dist/cli/tasks/watch.cjs +38 -0
  41. package/dist/cli/tasks/watch.mjs +37 -0
  42. package/dist/cli/templates/init.cjs +82 -0
  43. package/dist/cli/templates/init.mjs +78 -0
  44. package/dist/cli/types.cjs +13 -0
  45. package/dist/cli/types.mjs +13 -0
  46. package/dist/cli/utils.cjs +43 -0
  47. package/dist/cli/utils.mjs +41 -0
  48. package/dist/compile/classname-strategy.cjs +79 -0
  49. package/dist/compile/classname-strategy.mjs +77 -0
  50. package/dist/compile/classname.cjs +366 -0
  51. package/dist/compile/classname.mjs +360 -0
  52. package/dist/compile/index.cjs +238 -0
  53. package/dist/compile/index.mjs +235 -0
  54. package/dist/compile/jsx.cjs +803 -0
  55. package/dist/compile/jsx.mjs +800 -0
  56. package/dist/compile/prepared.cjs +88 -0
  57. package/dist/compile/prepared.mjs +87 -0
  58. package/dist/compile/runtime.cjs +33 -0
  59. package/dist/compile/runtime.mjs +32 -0
  60. package/dist/compile/transform.cjs +371 -0
  61. package/dist/compile/transform.mjs +369 -0
  62. package/dist/cx/index.cjs +93 -0
  63. package/dist/cx/index.mjs +85 -0
  64. package/dist/detect-fw/index.cjs +384 -0
  65. package/dist/detect-fw/index.mjs +379 -0
  66. package/dist/dev/client.cjs +39 -0
  67. package/dist/dev/client.mjs +38 -0
  68. package/dist/dev/plugin/browser.cjs +11 -0
  69. package/dist/dev/plugin/browser.mjs +9 -0
  70. package/dist/dev/plugin/server.cjs +86 -0
  71. package/dist/dev/plugin/server.mjs +78 -0
  72. package/dist/dev/port.cjs +46 -0
  73. package/dist/dev/port.mjs +43 -0
  74. package/dist/dev/runtime.cjs +28 -0
  75. package/dist/dev/runtime.mjs +29 -0
  76. package/dist/dev/server.cjs +808 -0
  77. package/dist/dev/server.mjs +805 -0
  78. package/dist/dev/shared.cjs +6 -0
  79. package/dist/dev/shared.mjs +5 -0
  80. package/dist/eslint-plugin/index.cjs +66 -0
  81. package/dist/eslint-plugin/index.mjs +66 -0
  82. package/dist/eslint-plugin/rules/classnames-only.cjs +68 -0
  83. package/dist/eslint-plugin/rules/classnames-only.mjs +68 -0
  84. package/dist/eslint-plugin/rules/format-classnames.cjs +137 -0
  85. package/dist/eslint-plugin/rules/format-classnames.mjs +136 -0
  86. package/dist/eslint-plugin/rules/no-unknown-classes.cjs +119 -0
  87. package/dist/eslint-plugin/rules/no-unknown-classes.mjs +119 -0
  88. package/dist/eslint-plugin/rules/prefer-classnames.cjs +69 -0
  89. package/dist/eslint-plugin/rules/prefer-classnames.mjs +69 -0
  90. package/dist/eslint-plugin/rules/prefer-token-values.cjs +197 -0
  91. package/dist/eslint-plugin/rules/prefer-token-values.mjs +197 -0
  92. package/dist/eslint-plugin/rules/props-only.cjs +115 -0
  93. package/dist/eslint-plugin/rules/props-only.mjs +115 -0
  94. package/dist/eslint-plugin/rules/redundant-cx.cjs +66 -0
  95. package/dist/eslint-plugin/rules/redundant-cx.mjs +66 -0
  96. package/dist/eslint-plugin/rules/require-prop-functions.cjs +130 -0
  97. package/dist/eslint-plugin/rules/require-prop-functions.mjs +130 -0
  98. package/dist/eslint-plugin/utils/api.cjs +30 -0
  99. package/dist/eslint-plugin/utils/api.mjs +29 -0
  100. package/dist/eslint-plugin/utils/ast.cjs +119 -0
  101. package/dist/eslint-plugin/utils/ast.mjs +112 -0
  102. package/dist/eslint-plugin/utils/boss-classes.cjs +185 -0
  103. package/dist/eslint-plugin/utils/boss-classes.mjs +175 -0
  104. package/dist/eslint-plugin/utils/defaults.cjs +99 -0
  105. package/dist/eslint-plugin/utils/defaults.mjs +93 -0
  106. package/dist/eslint-plugin/utils/format.cjs +20 -0
  107. package/dist/eslint-plugin/utils/format.mjs +19 -0
  108. package/dist/eslint-plugin/utils/order.cjs +76 -0
  109. package/dist/eslint-plugin/utils/order.mjs +76 -0
  110. package/dist/eslint-plugin/utils/property-order.cjs +449 -0
  111. package/dist/eslint-plugin/utils/property-order.mjs +448 -0
  112. package/dist/eslint-plugin/utils/static.cjs +36 -0
  113. package/dist/eslint-plugin/utils/static.mjs +35 -0
  114. package/dist/fontsource/directory.cjs +39588 -0
  115. package/dist/fontsource/directory.mjs +39587 -0
  116. package/dist/fontsource/server.cjs +291 -0
  117. package/dist/fontsource/server.mjs +282 -0
  118. package/dist/index.cjs +10 -0
  119. package/dist/index.mjs +6 -0
  120. package/dist/log/browser.cjs +28 -0
  121. package/dist/log/browser.mjs +28 -0
  122. package/dist/log/server.cjs +32 -0
  123. package/dist/log/server.mjs +30 -0
  124. package/dist/merge/index.cjs +590 -0
  125. package/dist/merge/index.mjs +586 -0
  126. package/dist/native/browser.cjs +78 -0
  127. package/dist/native/browser.mjs +77 -0
  128. package/dist/native/server.cjs +180 -0
  129. package/dist/native/server.mjs +176 -0
  130. package/dist/native/styleTypes.cjs +168 -0
  131. package/dist/native/styleTypes.mjs +164 -0
  132. package/dist/parser/classname/server.cjs +239 -0
  133. package/dist/parser/classname/server.mjs +232 -0
  134. package/dist/parser/jsx/browser.cjs +66 -0
  135. package/dist/parser/jsx/browser.mjs +63 -0
  136. package/dist/parser/jsx/extractCode.cjs +99 -0
  137. package/dist/parser/jsx/extractCode.mjs +98 -0
  138. package/dist/parser/jsx/extractPrepared.cjs +123 -0
  139. package/dist/parser/jsx/extractPrepared.mjs +122 -0
  140. package/dist/parser/jsx/extractProps.cjs +234 -0
  141. package/dist/parser/jsx/extractProps.mjs +232 -0
  142. package/dist/parser/jsx/isDOMProp.cjs +17 -0
  143. package/dist/parser/jsx/isDOMProp.mjs +15 -0
  144. package/dist/parser/jsx/native.cjs +110 -0
  145. package/dist/parser/jsx/native.mjs +108 -0
  146. package/dist/parser/jsx/runtime.cjs +4 -0
  147. package/dist/parser/jsx/runtime.mjs +3 -0
  148. package/dist/parser/jsx/server.cjs +278 -0
  149. package/dist/parser/jsx/server.mjs +268 -0
  150. package/dist/postcss/index.cjs +16 -0
  151. package/dist/postcss/index.mjs +16 -0
  152. package/dist/prop/at/runtime-only.cjs +90 -0
  153. package/dist/prop/at/runtime-only.mjs +88 -0
  154. package/dist/prop/at/server.cjs +282 -0
  155. package/dist/prop/at/server.mjs +268 -0
  156. package/dist/prop/at/shared.cjs +153 -0
  157. package/dist/prop/at/shared.mjs +144 -0
  158. package/dist/prop/bosswind/browser.cjs +18 -0
  159. package/dist/prop/bosswind/browser.mjs +16 -0
  160. package/dist/prop/bosswind/runtime-only.cjs +18 -0
  161. package/dist/prop/bosswind/runtime-only.mjs +16 -0
  162. package/dist/prop/bosswind/server.cjs +81 -0
  163. package/dist/prop/bosswind/server.mjs +72 -0
  164. package/dist/prop/bosswind/shared.cjs +861 -0
  165. package/dist/prop/bosswind/shared.mjs +855 -0
  166. package/dist/prop/bosswind/tailwind-theme.cjs +703 -0
  167. package/dist/prop/bosswind/tailwind-theme.mjs +702 -0
  168. package/dist/prop/child/runtime-only.cjs +18 -0
  169. package/dist/prop/child/runtime-only.mjs +15 -0
  170. package/dist/prop/child/server.cjs +81 -0
  171. package/dist/prop/child/server.mjs +72 -0
  172. package/dist/prop/css/getDtsTemplate.cjs +65 -0
  173. package/dist/prop/css/getDtsTemplate.mjs +63 -0
  174. package/dist/prop/css/runtime-only.cjs +14 -0
  175. package/dist/prop/css/runtime-only.mjs +13 -0
  176. package/dist/prop/css/server.cjs +99 -0
  177. package/dist/prop/css/server.mjs +90 -0
  178. package/dist/prop/pseudo/runtime-only.cjs +23 -0
  179. package/dist/prop/pseudo/runtime-only.mjs +21 -0
  180. package/dist/prop/pseudo/server.cjs +91 -0
  181. package/dist/prop/pseudo/server.mjs +82 -0
  182. package/dist/prop/pseudo/shared.cjs +61 -0
  183. package/dist/prop/pseudo/shared.mjs +60 -0
  184. package/dist/reset/server.cjs +34 -0
  185. package/dist/reset/server.mjs +26 -0
  186. package/dist/runtime/index.cjs +119 -0
  187. package/dist/runtime/index.mjs +118 -0
  188. package/dist/runtime/preact.cjs +4 -0
  189. package/dist/runtime/preact.mjs +3 -0
  190. package/dist/runtime/qwik.cjs +21 -0
  191. package/dist/runtime/qwik.mjs +18 -0
  192. package/dist/runtime/react.cjs +4 -0
  193. package/dist/runtime/react.mjs +3 -0
  194. package/dist/runtime/solid.cjs +15 -0
  195. package/dist/runtime/solid.mjs +14 -0
  196. package/dist/runtime/stencil.cjs +25 -0
  197. package/dist/runtime/stencil.mjs +21 -0
  198. package/dist/runtime/style.cjs +14 -0
  199. package/dist/runtime/style.mjs +13 -0
  200. package/dist/shared/boundaries.cjs +288 -0
  201. package/dist/shared/boundaries.mjs +285 -0
  202. package/dist/shared/customCss.cjs +212 -0
  203. package/dist/shared/customCss.mjs +211 -0
  204. package/dist/shared/debug.cjs +76 -0
  205. package/dist/shared/debug.mjs +74 -0
  206. package/dist/shared/file.cjs +21 -0
  207. package/dist/shared/file.mjs +19 -0
  208. package/dist/shared/framework.cjs +10 -0
  209. package/dist/shared/framework.mjs +9 -0
  210. package/dist/shared/json.cjs +58 -0
  211. package/dist/shared/json.mjs +57 -0
  212. package/dist/shared/types.cjs +11 -0
  213. package/dist/shared/types.mjs +10 -0
  214. package/dist/strategy/classic/runtime-only.cjs +190 -0
  215. package/dist/strategy/classic/runtime-only.mjs +186 -0
  216. package/dist/strategy/classname-first/runtime-only.cjs +138 -0
  217. package/dist/strategy/classname-first/runtime-only.mjs +134 -0
  218. package/dist/strategy/classname-first/server.cjs +139 -0
  219. package/dist/strategy/classname-first/server.mjs +133 -0
  220. package/dist/strategy/classname-only/server.cjs +43 -0
  221. package/dist/strategy/classname-only/server.mjs +35 -0
  222. package/dist/strategy/inline-first/browser.cjs +61 -0
  223. package/dist/strategy/inline-first/browser.mjs +58 -0
  224. package/dist/strategy/inline-first/runtime-only.cjs +159 -0
  225. package/dist/strategy/inline-first/runtime-only.mjs +155 -0
  226. package/dist/strategy/inline-first/server.cjs +92 -0
  227. package/dist/strategy/inline-first/server.mjs +83 -0
  228. package/dist/strategy/runtime/runtime-only.cjs +24 -0
  229. package/dist/strategy/runtime/runtime-only.mjs +22 -0
  230. package/dist/strategy/runtime/server.cjs +72 -0
  231. package/dist/strategy/runtime/server.mjs +63 -0
  232. package/dist/strategy/runtime-only/css.cjs +183 -0
  233. package/dist/strategy/runtime-only/css.mjs +181 -0
  234. package/dist/tasks/build.cjs +88 -0
  235. package/dist/tasks/build.mjs +84 -0
  236. package/dist/tasks/compile.cjs +12 -0
  237. package/dist/tasks/compile.mjs +12 -0
  238. package/dist/tasks/postcss.cjs +116 -0
  239. package/dist/tasks/postcss.mjs +113 -0
  240. package/dist/tasks/session.cjs +46 -0
  241. package/dist/tasks/session.mjs +42 -0
  242. package/dist/tasks/watch.cjs +102 -0
  243. package/dist/tasks/watch.mjs +99 -0
  244. package/dist/transform/cache.cjs +24 -0
  245. package/dist/transform/cache.mjs +21 -0
  246. package/dist/transform/processFile.cjs +26 -0
  247. package/dist/transform/processFile.mjs +24 -0
  248. package/dist/use/token/browser.cjs +65 -0
  249. package/dist/use/token/browser.mjs +61 -0
  250. package/dist/use/token/runtime-only.cjs +245 -0
  251. package/dist/use/token/runtime-only.mjs +239 -0
  252. package/dist/use/token/server.cjs +325 -0
  253. package/dist/use/token/server.mjs +313 -0
  254. package/dist/use/token/vars.cjs +47 -0
  255. package/dist/use/token/vars.mjs +46 -0
  256. package/package.json +300 -4
  257. package/src/api/config.d.ts +1 -0
  258. package/src/fontsource/types.d.ts +50 -0
  259. package/src/packages/document-create-element/createElement.browser.js +3 -0
  260. package/src/packages/document-create-element/createElement.js +7 -0
  261. package/src/packages/document-create-element/package.json +17 -0
  262. package/src/packages/is-css-prop/browser.js +13 -0
  263. package/src/packages/is-css-prop/index.js +13 -0
  264. package/src/packages/is-css-prop/package-lock.json +52 -0
  265. package/src/packages/is-css-prop/package.json +17 -0
  266. package/src/prop/css/csstype.json +4387 -0
  267. package/src/prop/css/package.json +3 -0
  268. package/src/reset/reset.css +259 -0
@@ -0,0 +1,805 @@
1
+ import { createApi } from "../api/server.mjs";
2
+ import { loadConfig } from "../api/config.mjs";
3
+ import { getTokens, propMap } from "../use/token/server.mjs";
4
+ import { DEFAULT_DEV_PORT } from "./shared.mjs";
5
+ import fs from "node:fs/promises";
6
+ import path from "node:path";
7
+ import { fileURLToPath } from "node:url";
8
+ import { WebSocketServer } from "ws";
9
+
10
+ //#region src/dev/server.ts
11
+ const DEFAULT_MAX_PORT = DEFAULT_DEV_PORT + 49;
12
+ async function startDevServer({ port = DEFAULT_DEV_PORT, maxPort = DEFAULT_MAX_PORT, host = "127.0.0.1" } = {}) {
13
+ let currentPort = port;
14
+ let server = null;
15
+ while (currentPort <= maxPort) try {
16
+ server = await listenOnPort(currentPort, host);
17
+ break;
18
+ } catch (error) {
19
+ if (isAddressInUse(error)) {
20
+ currentPort += 1;
21
+ continue;
22
+ }
23
+ throw error;
24
+ }
25
+ if (!server) throw new Error(`No available ports in range ${port}-${maxPort}`);
26
+ server.on("connection", (socket) => {
27
+ socket.on("message", async (data) => {
28
+ const message = parseClientMessage(data);
29
+ if (!message) return;
30
+ try {
31
+ if (message.type === "select") {
32
+ const entries = await inspectSelection(message.source);
33
+ socket.send(JSON.stringify({
34
+ type: "select-result",
35
+ id: message.id,
36
+ props: entries
37
+ }));
38
+ } else if (message.type === "edit") {
39
+ await applyEdit(message);
40
+ socket.send(JSON.stringify({
41
+ type: "edit-result",
42
+ id: message.id,
43
+ ok: true
44
+ }));
45
+ } else if (message.type === "add-prop") {
46
+ await applyAddProp(message);
47
+ socket.send(JSON.stringify({
48
+ type: "add-prop-result",
49
+ id: message.id,
50
+ ok: true
51
+ }));
52
+ } else if (message.type === "read-file") {
53
+ const content = await readFileForClient(message.path);
54
+ socket.send(JSON.stringify({
55
+ type: "read-file-result",
56
+ id: message.id,
57
+ content
58
+ }));
59
+ } else if (message.type === "write-file") {
60
+ await writeFileForClient(message.path, message.content);
61
+ socket.send(JSON.stringify({
62
+ type: "write-file-result",
63
+ id: message.id,
64
+ ok: true
65
+ }));
66
+ } else if (message.type === "tokens") {
67
+ const tokens = await getTokenSnapshot();
68
+ socket.send(JSON.stringify({
69
+ type: "tokens-result",
70
+ id: message.id,
71
+ tokens
72
+ }));
73
+ } else if (message.type === "boss-types") {
74
+ const content = await getBossTypes();
75
+ socket.send(JSON.stringify({
76
+ type: "boss-types-result",
77
+ id: message.id,
78
+ content
79
+ }));
80
+ }
81
+ } catch (error) {
82
+ const err = error instanceof Error ? error.message : String(error);
83
+ socket.send(JSON.stringify({
84
+ type: "error",
85
+ id: message.id,
86
+ message: err
87
+ }));
88
+ }
89
+ });
90
+ });
91
+ return {
92
+ server,
93
+ port: currentPort
94
+ };
95
+ }
96
+ const listenOnPort = (port, host) => {
97
+ return new Promise((resolve, reject) => {
98
+ const server = new WebSocketServer({
99
+ port,
100
+ host
101
+ });
102
+ const onError = (error) => {
103
+ server.removeListener("listening", onListening);
104
+ server.close();
105
+ reject(error);
106
+ };
107
+ const onListening = () => {
108
+ server.removeListener("error", onError);
109
+ resolve(server);
110
+ };
111
+ server.once("error", onError);
112
+ server.once("listening", onListening);
113
+ });
114
+ };
115
+ const isAddressInUse = (error) => {
116
+ return Boolean(error && typeof error === "object" && "code" in error && error.code === "EADDRINUSE");
117
+ };
118
+ const parseClientMessage = (data) => {
119
+ try {
120
+ const parsed = JSON.parse(data.toString());
121
+ if (!parsed || typeof parsed.type !== "string") return null;
122
+ return parsed;
123
+ } catch {
124
+ return null;
125
+ }
126
+ };
127
+ async function readFileForClient(filePath) {
128
+ if (!filePath || typeof filePath !== "string") return null;
129
+ const resolved = await resolveSourcePath(filePath);
130
+ if (!await fileExists(resolved)) return null;
131
+ return fs.readFile(resolved, "utf8");
132
+ }
133
+ async function writeFileForClient(filePath, content) {
134
+ if (!filePath || typeof filePath !== "string") throw new Error("Missing file path for write.");
135
+ const resolved = await resolveSourcePath(filePath);
136
+ await fs.writeFile(resolved, content ?? "");
137
+ }
138
+ async function getTokenSnapshot() {
139
+ await createApi(await loadConfig());
140
+ return {
141
+ tokens: getTokens() || {},
142
+ propGroups: Array.from(propMap.entries()).reduce((acc, [group, values]) => {
143
+ acc[group] = Array.from(values);
144
+ return acc;
145
+ }, {})
146
+ };
147
+ }
148
+ async function getBossTypes() {
149
+ const config = await loadConfig();
150
+ const baseDir = process.cwd();
151
+ const typesPath = path.join(baseDir, config.configDir ?? ".bo$$", "index.d.ts");
152
+ if (!await fileExists(typesPath)) return null;
153
+ return fs.readFile(typesPath, "utf8");
154
+ }
155
+ async function inspectSelection(source) {
156
+ const { code, offset, filePath, lineNumber, columnNumber, lineRange } = await readSourceFile(source);
157
+ const tag = findBossTagAtOffset(code, offset, lineRange);
158
+ if (!tag) throw new Error(`Unable to find <$$> element in ${filePath}:${lineNumber}:${columnNumber}`);
159
+ return buildPropEntries(tag, code).entries;
160
+ }
161
+ async function applyEdit(message) {
162
+ const { source, path: propPath, value: rawValue, kind } = message;
163
+ const { code, offset, filePath, lineNumber, columnNumber, lineRange } = await readSourceFile(source);
164
+ const tag = findBossTagAtOffset(code, offset, lineRange);
165
+ if (!tag) throw new Error(`Unable to find <$$> element in ${filePath}:${lineNumber}:${columnNumber}`);
166
+ const { index } = buildPropEntries(tag, code);
167
+ const target = index.get(propPath.join("."));
168
+ if (!target) throw new Error(`Unable to find prop "${propPath.join(".")}" for edit.`);
169
+ const parsedValue = parseValue(rawValue, kind);
170
+ const replacement = formatValue(parsedValue, kind, target.meta);
171
+ let start = 0;
172
+ let end = 0;
173
+ if (target.range) {
174
+ start = target.range.start;
175
+ end = target.range.end;
176
+ } else if (target.attrRange) {
177
+ start = target.attrRange.start;
178
+ end = target.attrRange.end;
179
+ const nextAttr = `${target.attrName ?? propPath[0] ?? "prop"}${kind === "boolean" && parsedValue === true ? "" : `={${replacement}}`}`;
180
+ const updated$1 = replaceText(code, start, end, nextAttr);
181
+ await fs.writeFile(filePath, updated$1);
182
+ return;
183
+ }
184
+ const updated = replaceText(code, start, end, replacement);
185
+ await fs.writeFile(filePath, updated);
186
+ }
187
+ async function applyAddProp(message) {
188
+ const { source, path: propPath, value: rawValue, kind } = message;
189
+ if (!propPath?.length) throw new Error("Missing prop path for add.");
190
+ if (propPath.length > 1) throw new Error("Nested prop insertion is not supported yet.");
191
+ const { code, offset, filePath, lineNumber, columnNumber, lineRange } = await readSourceFile(source);
192
+ const tag = findBossTagAtOffset(code, offset, lineRange);
193
+ if (!tag) throw new Error(`Unable to find <$$> element in ${filePath}:${lineNumber}:${columnNumber}`);
194
+ const { index } = buildPropEntries(tag, code);
195
+ const propKey = propPath.join(".");
196
+ if (index.get(propKey)) {
197
+ await applyEdit({
198
+ ...message,
199
+ type: "edit"
200
+ });
201
+ return;
202
+ }
203
+ const parsedValue = parseValue(rawValue, kind);
204
+ const replacement = formatValue(parsedValue, kind);
205
+ const attrName = propPath[0];
206
+ const attrText = formatAttribute(attrName, parsedValue, kind, replacement);
207
+ const insertAt = code[tag.end - 2] === "/" ? tag.end - 2 : tag.end - 1;
208
+ const updated = replaceText(code, insertAt, insertAt, `${insertAt > 0 && !/\s/.test(code[insertAt - 1]) ? " " : ""}${attrText}`);
209
+ await fs.writeFile(filePath, updated);
210
+ }
211
+ async function readSourceFile(source) {
212
+ if (!source?.fileName) throw new Error("Missing source file name for selection.");
213
+ const resolvedPath = await resolveSourcePath(source.fileName);
214
+ const lineNumber = Number.isFinite(source.lineNumber) ? Math.max(1, source.lineNumber) : 1;
215
+ const columnNumber = Number.isFinite(source.columnNumber) ? Math.max(1, source.columnNumber) : 1;
216
+ const code = await fs.readFile(resolvedPath, "utf8");
217
+ const lineOffsets = buildLineOffsets(code);
218
+ return {
219
+ code,
220
+ filePath: resolvedPath,
221
+ offset: offsetFromLineColumn(lineNumber, columnNumber - 1, lineOffsets),
222
+ lineRange: getLineRange(lineNumber, lineOffsets, code.length),
223
+ lineNumber,
224
+ columnNumber
225
+ };
226
+ }
227
+ const decodePath = (value) => {
228
+ try {
229
+ return decodeURIComponent(value);
230
+ } catch {
231
+ return value;
232
+ }
233
+ };
234
+ const isExplicitSource = (value) => {
235
+ return value.startsWith("file://") || value.startsWith("webpack://") || value.startsWith("webpack-internal://") || value.startsWith("http://") || value.startsWith("https://") || value.startsWith("[project]/") || path.isAbsolute(value);
236
+ };
237
+ const normalizeWebpackPath = (value) => {
238
+ let cleaned = value.replace(/^webpack-internal:\/\//, "").replace(/^webpack:\/\//, "");
239
+ cleaned = cleaned.replace(/^_N_E\//, "");
240
+ cleaned = cleaned.replace(/^\.\//, "");
241
+ cleaned = cleaned.replace(/^\/+/, "");
242
+ return decodePath(cleaned);
243
+ };
244
+ const stripQueryHash = (value) => value.split("?")[0].split("#")[0];
245
+ const resolveSourcePath = async (fileName, sourceRoot) => {
246
+ let candidate = stripQueryHash(fileName);
247
+ if (sourceRoot && !isExplicitSource(candidate)) {
248
+ let root = sourceRoot;
249
+ if (root.startsWith("file://")) root = fileURLToPath(root);
250
+ else if (root.startsWith("webpack://")) root = normalizeWebpackPath(root);
251
+ else if (root.startsWith("[project]/")) root = root.slice(10);
252
+ candidate = path.join(root, candidate);
253
+ }
254
+ if (candidate.startsWith("file://")) return fileURLToPath(candidate);
255
+ if (candidate.startsWith("http://") || candidate.startsWith("https://")) try {
256
+ const trimmed = decodePath(new URL(candidate).pathname).replace(/^\/+/, "");
257
+ return await findExistingPath(trimmed) ?? path.resolve(trimmed);
258
+ } catch {
259
+ return path.resolve(candidate);
260
+ }
261
+ if (candidate.startsWith("webpack://")) {
262
+ const cleaned = normalizeWebpackPath(candidate);
263
+ return await findExistingPath(cleaned) ?? path.resolve(cleaned);
264
+ }
265
+ if (candidate.startsWith("webpack-internal://")) {
266
+ const cleaned = normalizeWebpackPath(candidate);
267
+ return await findExistingPath(cleaned) ?? path.resolve(cleaned);
268
+ }
269
+ if (candidate.startsWith("[project]/")) {
270
+ const cleaned = decodePath(candidate.slice(10));
271
+ return await findExistingPath(cleaned) ?? path.resolve(cleaned);
272
+ }
273
+ if (path.isAbsolute(candidate)) return candidate;
274
+ return await findExistingPath(candidate) ?? path.resolve(candidate);
275
+ };
276
+ const findExistingPath = async (relativePath) => {
277
+ let current = process.cwd();
278
+ for (let i = 0; i < 8; i++) {
279
+ const candidate = path.resolve(current, relativePath);
280
+ if (await fileExists(candidate)) return candidate;
281
+ const parent = path.dirname(current);
282
+ if (parent === current) break;
283
+ current = parent;
284
+ }
285
+ return null;
286
+ };
287
+ const fileExists = async (filePath) => {
288
+ try {
289
+ await fs.access(filePath);
290
+ return true;
291
+ } catch {
292
+ return false;
293
+ }
294
+ };
295
+ const buildLineOffsets = (code) => {
296
+ const offsets = [0];
297
+ for (let i = 0; i < code.length; i++) if (code[i] === "\n") offsets.push(i + 1);
298
+ return offsets;
299
+ };
300
+ const offsetFromLineColumn = (lineNumber, columnNumber, offsets) => {
301
+ return (offsets[Math.max(0, lineNumber - 1)] ?? offsets[offsets.length - 1] ?? 0) + Math.max(0, columnNumber);
302
+ };
303
+ const getLineRange = (lineNumber, offsets, codeLength) => {
304
+ const lineIndex = Math.max(0, lineNumber - 1);
305
+ return {
306
+ start: offsets[lineIndex] ?? 0,
307
+ end: offsets[lineIndex + 1] ?? codeLength
308
+ };
309
+ };
310
+ const findBossTagAtOffset = (code, offset, lineRange) => {
311
+ const startIndex = Math.min(Math.max(offset, 0), code.length);
312
+ const minIndex = 0;
313
+ for (let i = startIndex; i >= minIndex; i--) {
314
+ if (code[i] !== "<") continue;
315
+ const next = code[i + 1];
316
+ if (next === "/" || next == null) continue;
317
+ if (!code.startsWith("$$", i + 1)) continue;
318
+ const tag = parseBossTag(code, i);
319
+ if (!tag) continue;
320
+ if (offset >= tag.start && offset <= tag.end) return tag;
321
+ if (lineRange && tag.start <= lineRange.end && tag.end >= lineRange.start) return tag;
322
+ }
323
+ return null;
324
+ };
325
+ const parseBossTag = (code, start) => {
326
+ let i = start + 1;
327
+ if (!code.startsWith("$$", i)) return null;
328
+ i += 2;
329
+ while (i < code.length && isTagNameChar(code[i])) i++;
330
+ const attrs = [];
331
+ while (i < code.length) {
332
+ i = skipWhitespace(code, i);
333
+ if (code[i] === "/" && code[i + 1] === ">") return {
334
+ start,
335
+ end: i + 2,
336
+ attrs
337
+ };
338
+ if (code[i] === ">") return {
339
+ start,
340
+ end: i + 1,
341
+ attrs
342
+ };
343
+ if (code[i] === "{" && code.slice(i, i + 4) === "{...") {
344
+ const end = findMatchingBrace(code, i);
345
+ if (end === -1) return null;
346
+ i = end + 1;
347
+ continue;
348
+ }
349
+ const nameStart = i;
350
+ while (i < code.length && isAttrNameChar(code[i])) i++;
351
+ if (i === nameStart) return null;
352
+ const name = code.slice(nameStart, i);
353
+ let attrRange = {
354
+ start: nameStart,
355
+ end: i
356
+ };
357
+ i = skipWhitespace(code, i);
358
+ let value = null;
359
+ if (code[i] === "=") {
360
+ i += 1;
361
+ i = skipWhitespace(code, i);
362
+ const valueStart = i;
363
+ if (code[i] === "\"" || code[i] === "'") {
364
+ const parsed = parseStringLiteral(code, i);
365
+ if (!parsed) return null;
366
+ value = parsed.node;
367
+ i = parsed.next;
368
+ } else if (code[i] === "{") {
369
+ const end = findMatchingBrace(code, i);
370
+ if (end === -1) return null;
371
+ value = parseExpression(code, i + 1, end);
372
+ i = end + 1;
373
+ } else {
374
+ const end = findAttributeValueEnd(code, i);
375
+ value = {
376
+ kind: "unknown",
377
+ range: {
378
+ start: valueStart,
379
+ end
380
+ },
381
+ code: code.slice(valueStart, end)
382
+ };
383
+ i = end;
384
+ }
385
+ attrRange = {
386
+ start: nameStart,
387
+ end: i
388
+ };
389
+ }
390
+ attrs.push({
391
+ name,
392
+ value,
393
+ range: attrRange
394
+ });
395
+ }
396
+ return null;
397
+ };
398
+ const isTagNameChar = (char) => /[A-Za-z0-9_$.\-]/.test(char);
399
+ const isAttrNameChar = (char) => /[A-Za-z0-9_$:\-]/.test(char);
400
+ const skipWhitespace = (code, index) => {
401
+ let i = index;
402
+ while (i < code.length && /\s/.test(code[i])) i++;
403
+ return i;
404
+ };
405
+ const findAttributeValueEnd = (code, index) => {
406
+ let i = index;
407
+ while (i < code.length && !/\s/.test(code[i]) && code[i] !== ">" && code[i] !== "/") i++;
408
+ return i;
409
+ };
410
+ const findMatchingBrace = (code, start) => {
411
+ let depth = 0;
412
+ let quote = null;
413
+ for (let i = start; i < code.length; i++) {
414
+ const char = code[i];
415
+ if (quote) {
416
+ if (char === "\\") {
417
+ i += 1;
418
+ continue;
419
+ }
420
+ if (char === quote) quote = null;
421
+ continue;
422
+ }
423
+ if (char === "\"" || char === "'" || char === "`") {
424
+ quote = char;
425
+ continue;
426
+ }
427
+ if (char === "{") depth += 1;
428
+ if (char === "}") {
429
+ depth -= 1;
430
+ if (depth === 0) return i;
431
+ }
432
+ }
433
+ return -1;
434
+ };
435
+ const parseStringLiteral = (code, start) => {
436
+ const quote = code[start];
437
+ let i = start + 1;
438
+ let value = "";
439
+ while (i < code.length) {
440
+ const char = code[i];
441
+ if (char === "\\") {
442
+ const next = code[i + 1];
443
+ if (next) {
444
+ value += next;
445
+ i += 2;
446
+ continue;
447
+ }
448
+ }
449
+ if (char === quote) {
450
+ const end = i + 1;
451
+ return {
452
+ node: {
453
+ kind: "string",
454
+ value,
455
+ range: {
456
+ start,
457
+ end
458
+ },
459
+ quote
460
+ },
461
+ next: end
462
+ };
463
+ }
464
+ value += char;
465
+ i += 1;
466
+ }
467
+ return null;
468
+ };
469
+ const parseExpression = (code, start, end) => {
470
+ const parser = new ExpressionParser(code, start, end);
471
+ const node = parser.parseValue();
472
+ parser.skipWhitespace();
473
+ if (!node || parser.index < end) return {
474
+ kind: "unknown",
475
+ range: {
476
+ start,
477
+ end
478
+ },
479
+ code: code.slice(start, end)
480
+ };
481
+ return node;
482
+ };
483
+ var ExpressionParser = class {
484
+ code;
485
+ index;
486
+ end;
487
+ constructor(code, start, end) {
488
+ this.code = code;
489
+ this.index = start;
490
+ this.end = end;
491
+ }
492
+ skipWhitespace() {
493
+ this.index = skipWhitespace(this.code, this.index);
494
+ }
495
+ parseValue() {
496
+ this.skipWhitespace();
497
+ if (this.index >= this.end) return null;
498
+ const char = this.code[this.index];
499
+ if (char === "\"" || char === "'") {
500
+ const parsed = parseStringLiteral(this.code, this.index);
501
+ if (!parsed || parsed.next > this.end) return null;
502
+ this.index = parsed.next;
503
+ return parsed.node;
504
+ }
505
+ if (char === "[") return this.parseArray();
506
+ if (char === "{") return this.parseObject();
507
+ if (char === "-" || /\d/.test(char)) return this.parseNumber();
508
+ if (this.code.startsWith("true", this.index)) {
509
+ const range = {
510
+ start: this.index,
511
+ end: this.index + 4
512
+ };
513
+ this.index += 4;
514
+ return {
515
+ kind: "boolean",
516
+ value: true,
517
+ range
518
+ };
519
+ }
520
+ if (this.code.startsWith("false", this.index)) {
521
+ const range = {
522
+ start: this.index,
523
+ end: this.index + 5
524
+ };
525
+ this.index += 5;
526
+ return {
527
+ kind: "boolean",
528
+ value: false,
529
+ range
530
+ };
531
+ }
532
+ return null;
533
+ }
534
+ parseNumber() {
535
+ const start = this.index;
536
+ let i = this.index;
537
+ if (this.code[i] === "-") i++;
538
+ while (i < this.end && /\d/.test(this.code[i])) i++;
539
+ if (i < this.end && this.code[i] === ".") {
540
+ i++;
541
+ while (i < this.end && /\d/.test(this.code[i])) i++;
542
+ }
543
+ const raw = this.code.slice(start, i);
544
+ const value = Number(raw);
545
+ if (Number.isNaN(value)) return null;
546
+ this.index = i;
547
+ return {
548
+ kind: "number",
549
+ value,
550
+ range: {
551
+ start,
552
+ end: i
553
+ }
554
+ };
555
+ }
556
+ parseArray() {
557
+ const start = this.index;
558
+ this.index += 1;
559
+ const values = [];
560
+ while (this.index < this.end) {
561
+ this.skipWhitespace();
562
+ if (this.code[this.index] === "]") {
563
+ const end = this.index + 1;
564
+ this.index = end;
565
+ return {
566
+ kind: "array",
567
+ value: values,
568
+ range: {
569
+ start,
570
+ end
571
+ }
572
+ };
573
+ }
574
+ const value = this.parseValue();
575
+ if (!value) return null;
576
+ values.push(value);
577
+ this.skipWhitespace();
578
+ if (this.code[this.index] === ",") {
579
+ this.index += 1;
580
+ continue;
581
+ }
582
+ if (this.code[this.index] === "]") continue;
583
+ return null;
584
+ }
585
+ return null;
586
+ }
587
+ parseObject() {
588
+ const start = this.index;
589
+ this.index += 1;
590
+ const value = {};
591
+ while (this.index < this.end) {
592
+ this.skipWhitespace();
593
+ if (this.code[this.index] === "}") {
594
+ const end = this.index + 1;
595
+ this.index = end;
596
+ return {
597
+ kind: "object",
598
+ value,
599
+ range: {
600
+ start,
601
+ end
602
+ }
603
+ };
604
+ }
605
+ const key = this.parseObjectKey();
606
+ if (!key) return null;
607
+ this.skipWhitespace();
608
+ if (this.code[this.index] !== ":") return null;
609
+ this.index += 1;
610
+ const val = this.parseValue();
611
+ if (!val) return null;
612
+ value[key] = val;
613
+ this.skipWhitespace();
614
+ if (this.code[this.index] === ",") {
615
+ this.index += 1;
616
+ continue;
617
+ }
618
+ if (this.code[this.index] === "}") continue;
619
+ return null;
620
+ }
621
+ return null;
622
+ }
623
+ parseObjectKey() {
624
+ this.skipWhitespace();
625
+ const char = this.code[this.index];
626
+ if (char === "\"" || char === "'") {
627
+ const parsed = parseStringLiteral(this.code, this.index);
628
+ if (!parsed || parsed.next > this.end) return null;
629
+ this.index = parsed.next;
630
+ return parsed.node.value;
631
+ }
632
+ const start = this.index;
633
+ if (!/[A-Za-z_$]/.test(char)) return null;
634
+ let i = this.index + 1;
635
+ while (i < this.end && /[A-Za-z0-9_$]/.test(this.code[i])) i++;
636
+ this.index = i;
637
+ return this.code.slice(start, i);
638
+ }
639
+ };
640
+ const buildPropEntries = (tag, code) => {
641
+ const entries = [];
642
+ const index = /* @__PURE__ */ new Map();
643
+ for (const attr of tag.attrs) {
644
+ if (!attr.value) {
645
+ entries.push({
646
+ path: [attr.name],
647
+ value: true,
648
+ editable: true,
649
+ kind: "boolean"
650
+ });
651
+ index.set(attr.name, {
652
+ attrName: attr.name,
653
+ attrRange: attr.range,
654
+ kind: "boolean"
655
+ });
656
+ continue;
657
+ }
658
+ collectParsedNode(attr.value, [attr.name], attr, entries, index, code);
659
+ }
660
+ return {
661
+ entries,
662
+ index
663
+ };
664
+ };
665
+ const collectParsedNode = (node, path$1, attr, entries, index, code) => {
666
+ if (node.kind === "string") {
667
+ entries.push({
668
+ path: path$1,
669
+ value: node.value,
670
+ editable: true,
671
+ kind: "string"
672
+ });
673
+ index.set(path$1.join("."), {
674
+ attrName: attr.name,
675
+ attrRange: attr.range,
676
+ range: node.range,
677
+ kind: "string",
678
+ meta: { quote: node.quote }
679
+ });
680
+ return;
681
+ }
682
+ if (node.kind === "number") {
683
+ entries.push({
684
+ path: path$1,
685
+ value: node.value,
686
+ editable: true,
687
+ kind: "number"
688
+ });
689
+ index.set(path$1.join("."), {
690
+ attrName: attr.name,
691
+ attrRange: attr.range,
692
+ range: node.range,
693
+ kind: "number"
694
+ });
695
+ return;
696
+ }
697
+ if (node.kind === "boolean") {
698
+ entries.push({
699
+ path: path$1,
700
+ value: node.value,
701
+ editable: true,
702
+ kind: "boolean"
703
+ });
704
+ index.set(path$1.join("."), {
705
+ attrName: attr.name,
706
+ attrRange: attr.range,
707
+ range: node.range,
708
+ kind: "boolean"
709
+ });
710
+ return;
711
+ }
712
+ if (node.kind === "array") {
713
+ if (node.value.every(isPrimitiveNode)) {
714
+ entries.push({
715
+ path: path$1,
716
+ value: node.value.map((item) => item.value),
717
+ editable: true,
718
+ kind: "array"
719
+ });
720
+ index.set(path$1.join("."), {
721
+ attrName: attr.name,
722
+ attrRange: attr.range,
723
+ range: node.range,
724
+ kind: "array"
725
+ });
726
+ } else entries.push({
727
+ path: path$1,
728
+ value: null,
729
+ editable: false,
730
+ kind: "expression",
731
+ code: codeFromRange(code, node.range)
732
+ });
733
+ return;
734
+ }
735
+ if (node.kind === "object") {
736
+ for (const [key, value] of Object.entries(node.value)) collectParsedNode(value, [...path$1, key], attr, entries, index, code);
737
+ return;
738
+ }
739
+ entries.push({
740
+ path: path$1,
741
+ value: null,
742
+ editable: false,
743
+ kind: "expression",
744
+ code: node.code
745
+ });
746
+ };
747
+ const isPrimitiveNode = (node) => node.kind === "string" || node.kind === "number" || node.kind === "boolean";
748
+ const codeFromRange = (code, range) => {
749
+ return code.slice(range.start, range.end);
750
+ };
751
+ const parseValue = (rawValue, kind) => {
752
+ if (kind === "number") {
753
+ const num = typeof rawValue === "number" ? rawValue : Number(rawValue);
754
+ if (Number.isNaN(num)) throw new Error("Invalid number value.");
755
+ return num;
756
+ }
757
+ if (kind === "boolean") {
758
+ if (typeof rawValue === "boolean") return rawValue;
759
+ if (rawValue === "true") return true;
760
+ if (rawValue === "false") return false;
761
+ throw new Error("Invalid boolean value.");
762
+ }
763
+ if (kind === "array") {
764
+ if (Array.isArray(rawValue)) return rawValue;
765
+ if (typeof rawValue === "string") {
766
+ const parsed = JSON.parse(rawValue);
767
+ if (!Array.isArray(parsed)) throw new Error("Array value must be a JSON array.");
768
+ return parsed;
769
+ }
770
+ throw new Error("Invalid array value.");
771
+ }
772
+ if (kind === "string") return String(rawValue);
773
+ return rawValue;
774
+ };
775
+ const formatValue = (value, kind, meta) => {
776
+ if (kind === "string") return formatString(String(value ?? ""), meta?.quote);
777
+ if (kind === "number") return String(value);
778
+ if (kind === "boolean") return value ? "true" : "false";
779
+ if (kind === "array") {
780
+ if (!Array.isArray(value)) throw new Error("Array value must be an array.");
781
+ return `[${value.map(formatArrayItem).join(", ")}]`;
782
+ }
783
+ return String(value);
784
+ };
785
+ const formatAttribute = (name, value, kind, formattedValue) => {
786
+ if (kind === "boolean" && value === true) return name;
787
+ if (kind === "string") return `${name}=${formattedValue}`;
788
+ return `${name}={${formattedValue}}`;
789
+ };
790
+ const formatArrayItem = (value) => {
791
+ if (typeof value === "string") return formatString(value, "\"");
792
+ if (typeof value === "number") return String(value);
793
+ if (typeof value === "boolean") return value ? "true" : "false";
794
+ return "null";
795
+ };
796
+ const formatString = (value, quote) => {
797
+ const useQuote = quote ?? "\"";
798
+ return `${useQuote}${value.replace(/\\/g, "\\\\").replace(new RegExp(useQuote, "g"), `\\${useQuote}`).replace(/\n/g, "\\n").replace(/\r/g, "\\r")}${useQuote}`;
799
+ };
800
+ const replaceText = (code, start, end, replacement) => {
801
+ return code.slice(0, start) + replacement + code.slice(end);
802
+ };
803
+
804
+ //#endregion
805
+ export { startDevServer };