@fynixorg/ui 1.0.20 → 1.0.22

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.
@@ -2,4 +2,5 @@ export * from "../runtime.js";
2
2
  export * from "../router/router.js";
3
3
  export { default as createFynix } from "../router/router.js";
4
4
  export { Fynix } from "../runtime.js";
5
+ export * from "../types/fnx.js";
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../fynix/index.ts"],"names":[],"mappings":"AAuBA,cAAc,eAAe,CAAC;AAE9B,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../fynix/index.ts"],"names":[],"mappings":"AAuBA,cAAc,eAAe,CAAC;AAE9B,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAGtC,cAAc,iBAAiB,CAAC"}
@@ -2,3 +2,4 @@ export * from "../runtime.js";
2
2
  export * from "../router/router.js";
3
3
  export { default as createFynix } from "../router/router.js";
4
4
  export { Fynix } from "../runtime.js";
5
+ export * from "../types/fnx.js";
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../fynix/index.ts"],
4
- "sourcesContent": ["/* MIT License\r\n\r\n* Copyright (c) 2026 Resty Gonzales\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in all\r\ncopies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r\n* SOFTWARE.\r\n */\r\n// fynix/index.js - Single entry point for all core functionality\r\nexport * from \"../runtime.js\";\r\n// Re-export Fynix namespace and hooks under new names\r\nexport * from \"../router/router.js\";\r\nexport { default as createFynix } from \"../router/router.js\";\r\nexport { Fynix } from \"../runtime.js\";\r\n"],
5
- "mappings": "AAuBA,cAAc;AAEd,cAAc;AACd,SAAoB,WAAXA,gBAA8B;AACvC,SAAS,aAAa;",
4
+ "sourcesContent": ["/* MIT License\r\n\r\n* Copyright (c) 2026 Resty Gonzales\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in all\r\ncopies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r\n* SOFTWARE.\r\n */\r\n// fynix/index.js - Single entry point for all core functionality\r\nexport * from \"../runtime.js\";\r\n// Re-export Fynix namespace and hooks under new names\r\nexport * from \"../router/router.js\";\r\nexport { default as createFynix } from \"../router/router.js\";\r\nexport { Fynix } from \"../runtime.js\";\r\n\r\n// Export types for .fnx module resolution\r\nexport * from \"../types/fnx.js\";\r\n"],
5
+ "mappings": "AAuBA,cAAc;AAEd,cAAc;AACd,SAAoB,WAAXA,gBAA8B;AACvC,SAAS,aAAa;AAGtB,cAAc;",
6
6
  "names": ["default"]
7
7
  }
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fynixorg/ui",
3
- "version": "1.0.19",
3
+ "version": "1.0.22",
4
4
  "type": "module",
5
5
  "description": "Core package for Fynix UI framework - A lightweight, reactive UI framework with TypeScript support.",
6
6
  "main": "./dist/fynix/index.js",
@@ -124,6 +124,10 @@
124
124
  "types": "./dist/plugins/vite-plugin-res.d.ts",
125
125
  "import": "./dist/plugins/vite-plugin-res.js"
126
126
  },
127
+ "./typescript-plugin": {
128
+ "import": "./dist/typescript-fynix-plugin/index.js",
129
+ "types": "./dist/typescript-fynix-plugin/index.d.ts"
130
+ },
127
131
  "./types": {
128
132
  "types": "./types/index.d.ts"
129
133
  },
@@ -0,0 +1,49 @@
1
+ export interface SourceMap {
2
+ originalToTransformed: Map<number, number>;
3
+ transformedToOriginal: Map<number, number>;
4
+ }
5
+ export interface ParsedFnxFile {
6
+ logic: string;
7
+ view: string;
8
+ style: string;
9
+ logicLang: "ts" | "js";
10
+ hasLogic: boolean;
11
+ hasView: boolean;
12
+ hasStyle: boolean;
13
+ isStyleScoped: boolean;
14
+ imports: string[];
15
+ exports: string[];
16
+ logicStartLine: number;
17
+ viewStartLine: number;
18
+ styleStartLine: number;
19
+ }
20
+ export interface TransformResult {
21
+ code: string;
22
+ lineMap: number[];
23
+ sourceMap: SourceMap;
24
+ }
25
+ export interface ParseOptions {
26
+ debug?: boolean;
27
+ logger?: (message: string) => void;
28
+ }
29
+ export interface TransformOptions extends ParseOptions {
30
+ filePath: string;
31
+ jsxFactory?: string;
32
+ includeStyleInjection?: boolean;
33
+ includeMetaInjection?: boolean;
34
+ }
35
+ export declare function parseFnxFile(source: string, options?: ParseOptions): ParsedFnxFile;
36
+ export declare function validateParsedFnx(parsed: ParsedFnxFile, filePath: string): void;
37
+ export declare function generateStyleId(filePath: string): string;
38
+ export declare function scopeStyles(css: string, scopeId: string): string;
39
+ export declare function buildSourceMap(originalContent: string, transformedContent: string, lineMap: number[]): SourceMap;
40
+ export declare function transformToComponent(parsed: ParsedFnxFile, options: TransformOptions): TransformResult;
41
+ export declare function transformToTsx(source: string, options?: ParseOptions): TransformResult;
42
+ export declare function getLineAndCharacterOfPosition(text: string, pos: number): {
43
+ line: number;
44
+ character: number;
45
+ };
46
+ export declare function getPositionOfLineAndCharacter(text: string, line: number, character: number): number;
47
+ export declare function mapTransformedToOriginal(position: number, transformedCode: string, originalContent: string, lineMap: number[], sourceMap: SourceMap): number;
48
+ export declare function mapOriginalToTransformed(position: number, transformedCode: string, originalContent: string, lineMap: number[], sourceMap: SourceMap): number;
49
+ //# sourceMappingURL=fnx-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fnx-parser.d.ts","sourceRoot":"","sources":["../../parser/fnx-parser.ts"],"names":[],"mappings":"AAgCA,MAAM,WAAW,SAAS;IACtB,qBAAqB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,qBAAqB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9C;AAKD,MAAM,WAAW,aAAa;IAE1B,KAAK,EAAE,MAAM,CAAC;IAEd,IAAI,EAAE,MAAM,CAAC;IAEb,KAAK,EAAE,MAAM,CAAC;IAEd,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IAEvB,QAAQ,EAAE,OAAO,CAAC;IAElB,OAAO,EAAE,OAAO,CAAC;IAEjB,QAAQ,EAAE,OAAO,CAAC;IAElB,aAAa,EAAE,OAAO,CAAC;IAEvB,OAAO,EAAE,MAAM,EAAE,CAAC;IAElB,OAAO,EAAE,MAAM,EAAE,CAAC;IAElB,cAAc,EAAE,MAAM,CAAC;IAEvB,aAAa,EAAE,MAAM,CAAC;IAEtB,cAAc,EAAE,MAAM,CAAC;CAC1B;AAKD,MAAM,WAAW,eAAe;IAE5B,IAAI,EAAE,MAAM,CAAC;IAEb,OAAO,EAAE,MAAM,EAAE,CAAC;IAElB,SAAS,EAAE,SAAS,CAAC;CACxB;AAKD,MAAM,WAAW,YAAY;IAEzB,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAKD,MAAM,WAAW,gBAAiB,SAAQ,YAAY;IAElD,QAAQ,EAAE,MAAM,CAAC;IAEjB,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAEhC,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAClC;AAcD,wBAAgB,YAAY,CACxB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,YAAiB,GAC3B,aAAa,CAuJf;AAUD,wBAAgB,iBAAiB,CAC7B,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,MAAM,GACjB,IAAI,CAyCN;AASD,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQxD;AAKD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAsBhE;AAKD,wBAAgB,cAAc,CAC1B,eAAe,EAAE,MAAM,EACvB,kBAAkB,EAAE,MAAM,EAC1B,OAAO,EAAE,MAAM,EAAE,GAClB,SAAS,CAiDX;AAUD,wBAAgB,oBAAoB,CAChC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,gBAAgB,GAC1B,eAAe,CAiKjB;AAUD,wBAAgB,cAAc,CAC1B,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,YAAiB,GAC3B,eAAe,CA6HjB;AA6CD,wBAAgB,6BAA6B,CACzC,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,GACZ;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAiBrC;AAKD,wBAAgB,6BAA6B,CACzC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GAClB,MAAM,CAWR;AAKD,wBAAgB,wBAAwB,CACpC,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,MAAM,EACvB,eAAe,EAAE,MAAM,EACvB,OAAO,EAAE,MAAM,EAAE,EACjB,SAAS,EAAE,SAAS,GACrB,MAAM,CAmBR;AAKD,wBAAgB,wBAAwB,CACpC,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,MAAM,EACvB,eAAe,EAAE,MAAM,EACvB,OAAO,EAAE,MAAM,EAAE,EACjB,SAAS,EAAE,SAAS,GACrB,MAAM,CAkBR"}
@@ -0,0 +1,483 @@
1
+ export function parseFnxFile(source, options = {}) {
2
+ const { debug = false, logger = console.log } = options;
3
+ const result = {
4
+ logic: "",
5
+ view: "",
6
+ style: "",
7
+ logicLang: "ts",
8
+ hasLogic: false,
9
+ hasView: false,
10
+ hasStyle: false,
11
+ isStyleScoped: false,
12
+ imports: [],
13
+ exports: [],
14
+ logicStartLine: 0,
15
+ viewStartLine: 0,
16
+ styleStartLine: 0,
17
+ };
18
+ const logicMatch = source.match(/<logic\s+setup\s*=\s*["']?(ts|js)["']?\s*>([\s\S]*?)<\/logic>/i);
19
+ if (logicMatch && logicMatch[1] && logicMatch[2] !== undefined) {
20
+ result.hasLogic = true;
21
+ result.logicLang = logicMatch[1].toLowerCase();
22
+ const beforeLogic = source.slice(0, logicMatch.index);
23
+ const beforeLineCount = beforeLogic.split("\n").length - 1;
24
+ const openingTag = logicMatch[0].substring(0, logicMatch[0].indexOf(">") + 1);
25
+ const tagLineCount = openingTag.split("\n").length - 1;
26
+ result.logicStartLine = beforeLineCount + tagLineCount + 1;
27
+ const rawLogic = logicMatch[2].trim();
28
+ const leadingNewlines = logicMatch[2].match(/^\n*/)?.[0].length || 0;
29
+ result.logicStartLine += leadingNewlines;
30
+ const logicLines = rawLogic.split("\n");
31
+ const imports = [];
32
+ const exports = [];
33
+ const otherLogic = [];
34
+ let inExportBlock = false;
35
+ let exportBuffer = [];
36
+ let exportBraceDepth = 0;
37
+ for (let i = 0; i < logicLines.length; i++) {
38
+ const line = logicLines[i] ?? "";
39
+ const trimmed = line.trim();
40
+ if (inExportBlock) {
41
+ exportBuffer.push(line);
42
+ const openBraces = ((line && line.match(/{/g)) || []).length;
43
+ const closeBraces = ((line && line.match(/}/g)) || []).length;
44
+ exportBraceDepth += openBraces - closeBraces;
45
+ if (exportBraceDepth <= 0) {
46
+ exports.push(exportBuffer.join("\n"));
47
+ exportBuffer = [];
48
+ inExportBlock = false;
49
+ exportBraceDepth = 0;
50
+ }
51
+ continue;
52
+ }
53
+ if (trimmed.startsWith("import ")) {
54
+ imports.push(line ?? "");
55
+ }
56
+ else if (trimmed.startsWith("export ")) {
57
+ if (/export\s+\w+\s*=\s*{/.test(trimmed) || trimmed.endsWith("{")) {
58
+ inExportBlock = true;
59
+ exportBuffer = [line];
60
+ exportBraceDepth =
61
+ ((line && line.match(/{/g)) || []).length -
62
+ ((line && line.match(/}/g)) || []).length;
63
+ if (exportBraceDepth <= 0) {
64
+ exports.push(exportBuffer.join("\n"));
65
+ exportBuffer = [];
66
+ inExportBlock = false;
67
+ exportBraceDepth = 0;
68
+ }
69
+ }
70
+ else {
71
+ exports.push(line ?? "");
72
+ }
73
+ }
74
+ else if (trimmed) {
75
+ otherLogic.push(line ?? "");
76
+ }
77
+ }
78
+ if (exportBuffer.length > 0) {
79
+ exports.push(exportBuffer.join("\n"));
80
+ }
81
+ result.imports = imports;
82
+ result.exports = exports;
83
+ result.logic = otherLogic.join("\n");
84
+ if (debug) {
85
+ logger(`[FnxParser] Logic block: lang=${result.logicLang}, start=${result.logicStartLine}, imports=${imports.length}, exports=${exports.length}`);
86
+ }
87
+ }
88
+ const viewMatch = source.match(/<view\s*>([\s\S]*?)<\/view>/i);
89
+ if (viewMatch && viewMatch[1] !== undefined) {
90
+ result.hasView = true;
91
+ result.view = viewMatch[1].trim();
92
+ const beforeView = source.slice(0, viewMatch.index);
93
+ result.viewStartLine = beforeView.split("\n").length;
94
+ const leadingNewlines = viewMatch[1].match(/^\n*/)?.[0].length || 0;
95
+ result.viewStartLine += leadingNewlines;
96
+ if (debug) {
97
+ logger(`[FnxParser] View block: start=${result.viewStartLine}`);
98
+ }
99
+ }
100
+ const styleMatch = source.match(/<style(\s+scoped)?\s*>([\s\S]*?)<\/style>/i);
101
+ if (styleMatch && styleMatch[2] !== undefined) {
102
+ result.hasStyle = true;
103
+ result.isStyleScoped = !!styleMatch[1];
104
+ result.style = styleMatch[2].trim();
105
+ const beforeStyle = source.slice(0, styleMatch.index);
106
+ result.styleStartLine = beforeStyle.split("\n").length;
107
+ if (debug) {
108
+ logger(`[FnxParser] Style block: scoped=${result.isStyleScoped}, start=${result.styleStartLine}`);
109
+ }
110
+ }
111
+ return result;
112
+ }
113
+ export function validateParsedFnx(parsed, filePath) {
114
+ if (!parsed.hasView) {
115
+ throw new Error(`[FnxParser] Missing <view> block in ${filePath}. Every .fnx file must have a <view> section.`);
116
+ }
117
+ if (parsed.hasLogic && !["ts", "js"].includes(parsed.logicLang)) {
118
+ throw new Error(`[FnxParser] Invalid setup attribute in <logic> block in ${filePath}. Must be "ts" or "js".`);
119
+ }
120
+ if (parsed.hasLogic && parsed.logicLang === "js") {
121
+ const tsPatterns = [
122
+ { pattern: /\binterface\s+\w+/, name: "interface declaration" },
123
+ { pattern: /\btype\s+\w+\s*=/, name: "type alias" },
124
+ { pattern: /:\s*\w+(\[\]|<[^>]+>)?\s*[;,=)]/, name: "type annotation" },
125
+ { pattern: /<\w+>(?!\s*<)/, name: "generic type" },
126
+ { pattern: /\benum\s+\w+/, name: "enum declaration" },
127
+ { pattern: /\bas\s+\w+/, name: "type assertion" },
128
+ { pattern: /\bnamespace\s+\w+/, name: "namespace" },
129
+ { pattern: /\babstract\s+class/, name: "abstract class" },
130
+ {
131
+ pattern: /\bpublic\s+|private\s+|protected\s+/,
132
+ name: "access modifier",
133
+ },
134
+ ];
135
+ const allCode = parsed.logic + "\n" + parsed.imports.join("\n");
136
+ for (const { pattern, name } of tsPatterns) {
137
+ if (pattern.test(allCode)) {
138
+ throw new Error(`[FnxParser] TypeScript syntax detected (${name}) in ${filePath} with setup="js". ` +
139
+ `Either change to setup="ts" or remove TypeScript-specific syntax.`);
140
+ }
141
+ }
142
+ }
143
+ }
144
+ export function generateStyleId(filePath) {
145
+ let hash = 0;
146
+ for (let i = 0; i < filePath.length; i++) {
147
+ const char = filePath.charCodeAt(i);
148
+ hash = (hash << 5) - hash + char;
149
+ hash = hash & hash;
150
+ }
151
+ return `fynix-${Math.abs(hash).toString(36)}`;
152
+ }
153
+ export function scopeStyles(css, scopeId) {
154
+ const dataAttr = `[data-${scopeId}]`;
155
+ return css.replace(/([^{}]+)\{([^{}]*)\}/g, (match, selector, rules) => {
156
+ if (selector.trim().startsWith("@")) {
157
+ return match;
158
+ }
159
+ const selectors = selector.split(",").map((s) => {
160
+ const trimmed = s.trim();
161
+ const pseudoMatch = trimmed.match(/^(.+?)(::?[a-z-]+(?:\([^)]*\))?)$/i);
162
+ if (pseudoMatch) {
163
+ return `${dataAttr} ${pseudoMatch[1]}${pseudoMatch[2]}`;
164
+ }
165
+ return `${dataAttr} ${trimmed}`;
166
+ });
167
+ return `${selectors.join(", ")}{${rules}}`;
168
+ });
169
+ }
170
+ export function buildSourceMap(originalContent, transformedContent, lineMap) {
171
+ const originalToTransformed = new Map();
172
+ const transformedToOriginal = new Map();
173
+ const originalLines = originalContent.split("\n");
174
+ const transformedLines = transformedContent.split("\n");
175
+ let transformedPos = 0;
176
+ for (let tLine = 0; tLine < transformedLines.length; tLine++) {
177
+ const originalLine = lineMap[tLine];
178
+ if (originalLine !== undefined && originalLine >= 0 && originalLine < originalLines.length) {
179
+ let originalPos = 0;
180
+ for (let i = 0; i < originalLine; i++) {
181
+ const lineLen = originalLines[i];
182
+ originalPos += (lineLen?.length ?? 0) + 1;
183
+ }
184
+ transformedToOriginal.set(transformedPos, originalPos);
185
+ originalToTransformed.set(originalPos, transformedPos);
186
+ const transformedLineText = transformedLines[tLine] ?? "";
187
+ const originalLineText = originalLines[originalLine] ?? "";
188
+ const tTrimmed = transformedLineText.trimStart();
189
+ const oTrimmed = originalLineText.trimStart();
190
+ for (let char = 0; char < Math.min(tTrimmed.length, oTrimmed.length); char++) {
191
+ const tPos = transformedPos + char + (transformedLineText.length - tTrimmed.length);
192
+ const oPos = originalPos + char + (originalLineText.length - oTrimmed.length);
193
+ transformedToOriginal.set(tPos, oPos);
194
+ originalToTransformed.set(oPos, tPos);
195
+ }
196
+ }
197
+ const currentTransLine = transformedLines[tLine];
198
+ transformedPos += (currentTransLine?.length ?? 0) + 1;
199
+ }
200
+ return { originalToTransformed, transformedToOriginal };
201
+ }
202
+ export function transformToComponent(parsed, options) {
203
+ const { filePath, jsxFactory = "Fynix", includeStyleInjection = true, includeMetaInjection = true, debug = false, logger = console.log, } = options;
204
+ const styleId = generateStyleId(filePath);
205
+ const lines = [];
206
+ const lineMap = [];
207
+ const push = (line, origin = -1) => {
208
+ lines.push(line);
209
+ lineMap.push(origin);
210
+ };
211
+ push(`import { ${jsxFactory} } from '@fynixorg/ui';`);
212
+ if (parsed.imports.length > 0) {
213
+ parsed.imports.forEach((importLine, i) => {
214
+ push(importLine, parsed.logicStartLine + i);
215
+ });
216
+ }
217
+ push("");
218
+ if (parsed.hasStyle && includeStyleInjection) {
219
+ let processedStyle = parsed.style;
220
+ if (parsed.isStyleScoped) {
221
+ processedStyle = scopeStyles(parsed.style, styleId);
222
+ }
223
+ push(`// Inject styles`);
224
+ push(`if (typeof document !== 'undefined') {`);
225
+ push(` const styleId = '${styleId}';`);
226
+ push(` if (!document.getElementById(styleId)) {`);
227
+ push(` const styleEl = document.createElement('style');`);
228
+ push(` styleEl.id = styleId;`);
229
+ push(` styleEl.textContent = ${JSON.stringify(processedStyle)};`);
230
+ push(` document.head.appendChild(styleEl);`);
231
+ push(` }`);
232
+ push(`}`);
233
+ push("");
234
+ }
235
+ if (parsed.exports.length > 0) {
236
+ parsed.exports.forEach((exportLine) => {
237
+ const exportLines = exportLine.split("\n");
238
+ exportLines.forEach((line) => push(line));
239
+ });
240
+ push("");
241
+ }
242
+ push(`function FynixComponent(props = {}) {`);
243
+ if (parsed.hasLogic && parsed.logic.trim()) {
244
+ push(` // Component logic`);
245
+ const logicLines = parsed.logic.split("\n");
246
+ logicLines.forEach((line, i) => {
247
+ if (line.trim()) {
248
+ push(` ${line}`, parsed.logicStartLine + parsed.imports.length + i);
249
+ }
250
+ });
251
+ push("");
252
+ }
253
+ if (includeMetaInjection &&
254
+ parsed.exports.some((e) => e.trim().startsWith("export const meta"))) {
255
+ push(` if (typeof document !== "undefined" && typeof meta !== "undefined") {`);
256
+ push(` document.title = meta.title;`);
257
+ push(` const metaTags = [`);
258
+ push(` { name: "description", content: meta.description },`);
259
+ push(` { name: "keywords", content: meta.keywords },`);
260
+ push(` { property: "og:title", content: meta.ogTitle },`);
261
+ push(` { property: "og:description", content: meta.ogDescription },`);
262
+ push(` { property: "og:image", content: meta.ogImage },`);
263
+ push(` ];`);
264
+ push(` metaTags.forEach(({ name, property, content }) => {`);
265
+ push(` if (!content) return;`);
266
+ push(` let tag;`);
267
+ push(` if (name) {`);
268
+ push(` tag = document.querySelector(\`meta[name='\${name}']\`);`);
269
+ push(` if (!tag) {`);
270
+ push(` tag = document.createElement("meta");`);
271
+ push(` tag.setAttribute("name", name);`);
272
+ push(` document.head.appendChild(tag);`);
273
+ push(` }`);
274
+ push(` } else if (property) {`);
275
+ push(` tag = document.querySelector(\`meta[property='\${property}']\`);`);
276
+ push(` if (!tag) {`);
277
+ push(` tag = document.createElement("meta");`);
278
+ push(` tag.setAttribute("property", property);`);
279
+ push(` document.head.appendChild(tag);`);
280
+ push(` }`);
281
+ push(` }`);
282
+ push(` if (tag) tag.setAttribute("content", content);`);
283
+ push(` });`);
284
+ push(` }`);
285
+ push("");
286
+ }
287
+ if (parsed.hasView) {
288
+ push(` // Component view`);
289
+ if (parsed.isStyleScoped) {
290
+ push(` return (`);
291
+ push(` <div data-${styleId}="">`);
292
+ const viewLines = parsed.view.split("\n");
293
+ viewLines.forEach((line, i) => {
294
+ push(` ${line}`, parsed.viewStartLine + i);
295
+ });
296
+ push(` </div>`);
297
+ push(` );`);
298
+ }
299
+ else {
300
+ push(` return (`);
301
+ const viewLines = parsed.view.split("\n");
302
+ viewLines.forEach((line, i) => {
303
+ push(` ${line}`, parsed.viewStartLine + i);
304
+ });
305
+ push(` );`);
306
+ }
307
+ }
308
+ else {
309
+ push(` return null;`);
310
+ }
311
+ push(`}`);
312
+ push("");
313
+ push(`export default FynixComponent;`);
314
+ const code = lines.join("\n");
315
+ const sourceMap = buildSourceMap(createOriginalContent(parsed), code, lineMap);
316
+ if (debug) {
317
+ logger(`[FnxParser] Transformed ${filePath}: ${code.length} bytes`);
318
+ }
319
+ return { code, lineMap, sourceMap };
320
+ }
321
+ export function transformToTsx(source, options = {}) {
322
+ const { debug = false, logger = console.log } = options;
323
+ const lines = [];
324
+ const lineMap = [];
325
+ const push = (line, origin = -1) => {
326
+ lines.push(line);
327
+ lineMap.push(origin);
328
+ };
329
+ const logicMatch = source.match(/<logic\s+setup\s*=\s*["']?(ts|js)["']?\s*>([\s\S]*?)<\/logic>/i);
330
+ let logicStart = 0;
331
+ let logicContent = "";
332
+ if (logicMatch) {
333
+ const before = source.slice(0, logicMatch.index);
334
+ const beforeLineCount = before.split("\n").length - 1;
335
+ const openingTag = logicMatch[0].substring(0, logicMatch[0].indexOf(">") + 1);
336
+ const tagLineCount = openingTag.split("\n").length - 1;
337
+ logicStart = beforeLineCount + tagLineCount + 1;
338
+ logicContent = logicMatch[2] ?? "";
339
+ const leadingNewlines = logicContent.match(/^\n*/)?.[0].length || 0;
340
+ logicStart += leadingNewlines;
341
+ logicContent = logicContent.trimStart();
342
+ if (debug) {
343
+ logger(`[FnxParser TSX] Logic starts at line ${logicStart}`);
344
+ }
345
+ }
346
+ const userImports = [];
347
+ const userBody = [];
348
+ let hasFynixImport = false;
349
+ if (logicContent) {
350
+ const logicLines = logicContent.split("\n");
351
+ const lastLine = logicLines[logicLines.length - 1];
352
+ if (logicLines.length > 0 &&
353
+ lastLine !== undefined &&
354
+ lastLine.trim() === "") {
355
+ logicLines.pop();
356
+ }
357
+ logicLines.forEach((line, i) => {
358
+ const trimmed = line.trim();
359
+ const origin = logicStart + i;
360
+ if (trimmed.startsWith("import ")) {
361
+ userImports.push({ line, origin });
362
+ if (trimmed.includes("@fynixorg/ui")) {
363
+ hasFynixImport = true;
364
+ }
365
+ }
366
+ else {
367
+ userBody.push({ line, origin });
368
+ }
369
+ });
370
+ }
371
+ userImports.forEach((item) => {
372
+ push(item.line, item.origin);
373
+ });
374
+ if (!hasFynixImport) {
375
+ push(`import { Fynix } from "@fynixorg/ui";`);
376
+ }
377
+ push("");
378
+ push("export default function FynixComponent(props: any = {}) {");
379
+ userBody.forEach((item) => {
380
+ push(" " + item.line, item.origin);
381
+ });
382
+ const viewMatch = source.match(/<view\s*>([\s\S]*?)<\/view>/i);
383
+ if (viewMatch) {
384
+ let viewContent = viewMatch[1] ?? "";
385
+ const before = source.slice(0, viewMatch.index);
386
+ const beforeLineCount = before.split("\n").length - 1;
387
+ let viewStart = beforeLineCount + 1;
388
+ const leadingNewlines = viewContent.match(/^\n*/)?.[0].length || 0;
389
+ viewStart += leadingNewlines;
390
+ viewContent = viewContent.trimStart();
391
+ if (debug) {
392
+ logger(`[FnxParser TSX] View starts at line ${viewStart}`);
393
+ }
394
+ push(" return (");
395
+ const viewLines = viewContent.split("\n");
396
+ viewLines.forEach((line, i) => {
397
+ push(" " + line, viewStart + i);
398
+ });
399
+ push(" );");
400
+ }
401
+ else {
402
+ push(" return null;");
403
+ }
404
+ push("}");
405
+ const code = lines.join("\n");
406
+ const sourceMap = buildSourceMap(source, code, lineMap);
407
+ return { code, lineMap, sourceMap };
408
+ }
409
+ function createOriginalContent(parsed) {
410
+ const parts = [];
411
+ if (parsed.hasLogic) {
412
+ parts.push(`<logic setup="${parsed.logicLang}">`);
413
+ if (parsed.imports.length > 0) {
414
+ parts.push(parsed.imports.join("\n"));
415
+ }
416
+ if (parsed.exports.length > 0) {
417
+ parts.push(parsed.exports.join("\n"));
418
+ }
419
+ if (parsed.logic.trim()) {
420
+ parts.push(parsed.logic);
421
+ }
422
+ parts.push("</logic>");
423
+ }
424
+ if (parsed.hasView) {
425
+ parts.push(`<view>`);
426
+ parts.push(parsed.view);
427
+ parts.push("</view>");
428
+ }
429
+ if (parsed.hasStyle) {
430
+ parts.push(parsed.isStyleScoped ? `<style scoped>` : `<style>`);
431
+ parts.push(parsed.style);
432
+ parts.push("</style>");
433
+ }
434
+ return parts.join("\n");
435
+ }
436
+ export function getLineAndCharacterOfPosition(text, pos) {
437
+ const lines = text.split("\n");
438
+ let currentPos = 0;
439
+ for (let line = 0; line < lines.length; line++) {
440
+ const currentLine = lines[line];
441
+ const lineLength = (currentLine?.length ?? 0) + 1;
442
+ if (currentPos + lineLength > pos) {
443
+ return {
444
+ line,
445
+ character: pos - currentPos,
446
+ };
447
+ }
448
+ currentPos += lineLength;
449
+ }
450
+ return { line: Math.max(0, lines.length - 1), character: 0 };
451
+ }
452
+ export function getPositionOfLineAndCharacter(text, line, character) {
453
+ const lines = text.split("\n");
454
+ let pos = 0;
455
+ for (let i = 0; i < line && i < lines.length; i++) {
456
+ const currentLine = lines[i];
457
+ pos += (currentLine?.length ?? 0) + 1;
458
+ }
459
+ const targetLine = lines[line];
460
+ return pos + Math.min(character, targetLine?.length ?? 0);
461
+ }
462
+ export function mapTransformedToOriginal(position, transformedCode, originalContent, lineMap, sourceMap) {
463
+ if (sourceMap.transformedToOriginal.has(position)) {
464
+ return sourceMap.transformedToOriginal.get(position);
465
+ }
466
+ const { line: tLine, character: tChar } = getLineAndCharacterOfPosition(transformedCode, position);
467
+ const originalLine = lineMap[tLine];
468
+ if (originalLine === undefined || originalLine < 0) {
469
+ return 0;
470
+ }
471
+ return getPositionOfLineAndCharacter(originalContent, originalLine, tChar);
472
+ }
473
+ export function mapOriginalToTransformed(position, transformedCode, originalContent, lineMap, sourceMap) {
474
+ if (sourceMap.originalToTransformed.has(position)) {
475
+ return sourceMap.originalToTransformed.get(position);
476
+ }
477
+ const { line: oLine, character: oChar } = getLineAndCharacterOfPosition(originalContent, position);
478
+ const tLine = lineMap.indexOf(oLine);
479
+ if (tLine < 0) {
480
+ return 0;
481
+ }
482
+ return getPositionOfLineAndCharacter(transformedCode, tLine, oChar);
483
+ }
@@ -1,4 +1,4 @@
1
- import { type TransformOptions } from "esbuild";
1
+ import { type TransformOptions as EsbuildTransformOptions } from "esbuild";
2
2
  import * as ts from "typescript";
3
3
  interface FynixPluginOptions {
4
4
  jsxFactory?: string;
@@ -6,25 +6,13 @@ interface FynixPluginOptions {
6
6
  include?: string[];
7
7
  exclude?: string[];
8
8
  sourcemap?: boolean;
9
- esbuildOptions?: Partial<TransformOptions>;
9
+ esbuildOptions?: Partial<EsbuildTransformOptions>;
10
10
  enableSFC?: boolean;
11
11
  debug?: boolean;
12
12
  showGeneratedCode?: boolean;
13
13
  typeCheck?: boolean;
14
14
  tsConfig?: ts.CompilerOptions;
15
15
  }
16
- interface SFCParsedResult {
17
- logic: string;
18
- view: string;
19
- style: string;
20
- logicLang: "js" | "ts";
21
- hasLogic: boolean;
22
- hasView: boolean;
23
- hasStyle: boolean;
24
- isStyleScoped: boolean;
25
- imports: string[];
26
- exports: string[];
27
- }
28
16
  declare class TypeScriptChecker {
29
17
  private compilerOptions;
30
18
  private virtualFiles;
@@ -37,5 +25,5 @@ declare class TypeScriptChecker {
37
25
  }
38
26
  export default function fynixPlugin(options?: FynixPluginOptions): any;
39
27
  export { fynixPlugin, TypeScriptChecker };
40
- export type { FynixPluginOptions, SFCParsedResult };
28
+ export type { FynixPluginOptions };
41
29
  //# sourceMappingURL=vite-plugin-res.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"vite-plugin-res.d.ts","sourceRoot":"","sources":["../../plugins/vite-plugin-res.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAa,KAAK,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAG3D,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AA8IjC,UAAU,kBAAkB;IAK1B,UAAU,CAAC,EAAE,MAAM,CAAC;IAMpB,WAAW,CAAC,EAAE,MAAM,CAAC;IAMrB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAMnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAMnB,SAAS,CAAC,EAAE,OAAO,CAAC;IAKpB,cAAc,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAM3C,SAAS,CAAC,EAAE,OAAO,CAAC;IAMpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAMhB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAM5B,SAAS,CAAC,EAAE,OAAO,CAAC;IAKpB,QAAQ,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC;CAC/B;AAaD,UAAU,eAAe;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,OAAO,CAAC;IACvB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAgkBD,cAAM,iBAAiB;IACrB,OAAO,CAAC,eAAe,CAAqB;IAC5C,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,OAAO,CAA2B;gBAE9B,aAAa,CAAC,EAAE,EAAE,CAAC,eAAe;IAuB9C,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAKhD,OAAO,CAAC,kBAAkB;IA8C1B,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE;IA0ErC,KAAK,IAAI,IAAI;CAId;AAKD,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,OAAO,GAAE,kBAAuB,GAAG,GAAG,CAwWzE;AAED,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,CAAC;AAC1C,YAAY,EAAE,kBAAkB,EAAE,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"vite-plugin-res.d.ts","sourceRoot":"","sources":["../../plugins/vite-plugin-res.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,gBAAgB,IAAI,uBAAuB,EACjD,MAAM,SAAS,CAAC;AAGjB,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAyBjC,UAAU,kBAAkB;IAK1B,UAAU,CAAC,EAAE,MAAM,CAAC;IAMpB,WAAW,CAAC,EAAE,MAAM,CAAC;IAMrB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAMnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAMnB,SAAS,CAAC,EAAE,OAAO,CAAC;IAKpB,cAAc,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAMlD,SAAS,CAAC,EAAE,OAAO,CAAC;IAMpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAMhB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAM5B,SAAS,CAAC,EAAE,OAAO,CAAC;IAKpB,QAAQ,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC;CAC/B;AAaD,cAAM,iBAAiB;IACrB,OAAO,CAAC,eAAe,CAAqB;IAC5C,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,OAAO,CAA2B;gBAE9B,aAAa,CAAC,EAAE,EAAE,CAAC,eAAe;IAuB9C,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAKhD,OAAO,CAAC,kBAAkB;IA8C1B,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE;IAmErC,KAAK,IAAI,IAAI;CAId;AAKD,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,OAAO,GAAE,kBAAuB,GAAG,GAAG,CAqOzE;AAED,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,CAAC;AAC1C,YAAY,EAAE,kBAAkB,EAAE,CAAC"}