pulse-js-framework 1.7.30 → 1.7.32

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.
package/cli/build.js CHANGED
@@ -7,9 +7,13 @@
7
7
  import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync, statSync, copyFileSync } from 'fs';
8
8
  import { join, extname, relative, dirname } from 'path';
9
9
  import { compile } from '../compiler/index.js';
10
+ import { preprocessStylesSync, isSassAvailable, getSassVersion } from '../compiler/preprocessor.js';
10
11
  import { log } from './logger.js';
11
12
  import { createTimer, createProgressBar, formatDuration, createSpinner } from './utils/cli-ui.js';
12
13
 
14
+ // SASS availability (checked once at build start)
15
+ let sassAvailable = false;
16
+
13
17
  /**
14
18
  * Build project for production
15
19
  */
@@ -34,6 +38,13 @@ export async function buildProject(args) {
34
38
 
35
39
  log.info('Building with Pulse compiler...\n');
36
40
 
41
+ // Check for SASS availability
42
+ sassAvailable = isSassAvailable();
43
+ if (sassAvailable) {
44
+ const version = getSassVersion();
45
+ log.info(` SASS support enabled (sass ${version || 'unknown'})`);
46
+ }
47
+
37
48
  // Create output directory
38
49
  if (!existsSync(outDir)) {
39
50
  mkdirSync(outDir, { recursive: true });
@@ -140,8 +151,30 @@ function processDirectory(srcDir, outDir, progress = null) {
140
151
  });
141
152
 
142
153
  if (result.success) {
154
+ let code = result.code;
155
+
156
+ // Preprocess SASS/SCSS in style blocks if sass is available
157
+ if (sassAvailable) {
158
+ const stylesMatch = code.match(/const styles = `([\s\S]*?)`;/);
159
+ if (stylesMatch) {
160
+ try {
161
+ const preprocessed = preprocessStylesSync(stylesMatch[1], {
162
+ filename: srcPath,
163
+ loadPaths: [dirname(srcPath)],
164
+ compressed: true
165
+ });
166
+
167
+ if (preprocessed.wasSass) {
168
+ code = code.replace(stylesMatch[0], `const styles = \`${preprocessed.css}\`;`);
169
+ }
170
+ } catch (sassError) {
171
+ log.warn(` SASS warning in ${file}: ${sassError.message}`);
172
+ }
173
+ }
174
+ }
175
+
143
176
  const outPath = join(outDir, file.replace('.pulse', '.js'));
144
- writeFileSync(outPath, result.code);
177
+ writeFileSync(outPath, code);
145
178
  } else {
146
179
  log.error(` Error compiling ${file}:`);
147
180
  for (const error of result.errors) {
package/cli/dev.js CHANGED
@@ -6,10 +6,14 @@
6
6
 
7
7
  import { createServer } from 'http';
8
8
  import { readFileSync, existsSync, statSync, watch } from 'fs';
9
- import { join, extname, resolve } from 'path';
9
+ import { join, extname, resolve, dirname } from 'path';
10
10
  import { compile } from '../compiler/index.js';
11
+ import { preprocessStylesSync, isSassAvailable, getSassVersion } from '../compiler/preprocessor.js';
11
12
  import { log } from './logger.js';
12
13
 
14
+ // SASS availability (checked once at server start)
15
+ let sassAvailable = false;
16
+
13
17
  const MIME_TYPES = {
14
18
  '.html': 'text/html',
15
19
  '.js': 'application/javascript',
@@ -87,6 +91,13 @@ export async function startDevServer(args) {
87
91
  // Vite not available, use built-in server
88
92
  }
89
93
 
94
+ // Check for SASS availability
95
+ sassAvailable = isSassAvailable();
96
+ if (sassAvailable) {
97
+ const version = getSassVersion();
98
+ log.info(`SASS support enabled (sass ${version || 'unknown'})`);
99
+ }
100
+
90
101
  // Built-in development server
91
102
  const server = createServer(async (req, res) => {
92
103
  const url = new URL(req.url, `http://localhost:${port}`);
@@ -128,11 +139,31 @@ export async function startDevServer(args) {
128
139
  });
129
140
 
130
141
  if (result.success) {
142
+ let code = result.code;
143
+
144
+ // Preprocess SASS/SCSS if available
145
+ if (sassAvailable) {
146
+ const stylesMatch = code.match(/const styles = `([\s\S]*?)`;/);
147
+ if (stylesMatch) {
148
+ try {
149
+ const preprocessed = preprocessStylesSync(stylesMatch[1], {
150
+ filename: filePath,
151
+ loadPaths: [dirname(filePath)]
152
+ });
153
+ if (preprocessed.wasSass) {
154
+ code = code.replace(stylesMatch[0], `const styles = \`${preprocessed.css}\`;`);
155
+ }
156
+ } catch (sassError) {
157
+ console.warn(`[Pulse] SASS warning: ${sassError.message}`);
158
+ }
159
+ }
160
+ }
161
+
131
162
  res.writeHead(200, {
132
163
  'Content-Type': 'application/javascript',
133
164
  'Cache-Control': 'no-cache, no-store, must-revalidate'
134
165
  });
135
- res.end(result.code);
166
+ res.end(code);
136
167
  } else {
137
168
  const errorDetails = result.errors.map(e => `${e.message} at line ${e.line || '?'}:${e.column || '?'}`).join('\n');
138
169
  console.error(`[Pulse] Compilation error in ${filePath}:`, result.errors);
@@ -173,11 +204,31 @@ export async function startDevServer(args) {
173
204
  });
174
205
 
175
206
  if (result.success) {
207
+ let code = result.code;
208
+
209
+ // Preprocess SASS/SCSS if available
210
+ if (sassAvailable) {
211
+ const stylesMatch = code.match(/const styles = `([\s\S]*?)`;/);
212
+ if (stylesMatch) {
213
+ try {
214
+ const preprocessed = preprocessStylesSync(stylesMatch[1], {
215
+ filename: pulseFilePath,
216
+ loadPaths: [dirname(pulseFilePath)]
217
+ });
218
+ if (preprocessed.wasSass) {
219
+ code = code.replace(stylesMatch[0], `const styles = \`${preprocessed.css}\`;`);
220
+ }
221
+ } catch (sassError) {
222
+ console.warn(`[Pulse] SASS warning: ${sassError.message}`);
223
+ }
224
+ }
225
+ }
226
+
176
227
  res.writeHead(200, {
177
228
  'Content-Type': 'application/javascript',
178
229
  'Cache-Control': 'no-cache, no-store, must-revalidate'
179
230
  });
180
- res.end(result.code);
231
+ res.end(code);
181
232
  } else {
182
233
  res.writeHead(500, { 'Content-Type': 'text/plain' });
183
234
  res.end(`Compilation error: ${result.errors.map(e => e.message).join('\n')}`);
package/cli/index.js CHANGED
@@ -15,8 +15,14 @@ const __filename = fileURLToPath(import.meta.url);
15
15
  const __dirname = dirname(__filename);
16
16
 
17
17
  // Version - read dynamically from package.json
18
- const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
19
- const VERSION = pkg.version;
18
+ let VERSION = '0.0.0';
19
+ try {
20
+ const pkgContent = readFileSync(join(__dirname, '..', 'package.json'), 'utf-8');
21
+ const pkg = JSON.parse(pkgContent);
22
+ VERSION = pkg.version || VERSION;
23
+ } catch (err) {
24
+ log.warn(`Could not read package.json: ${err.message}`);
25
+ }
20
26
 
21
27
  // Available example templates
22
28
  const TEMPLATES = {
@@ -683,10 +689,19 @@ async function initProject(args) {
683
689
 
684
690
  if (existsSync(pkgPath)) {
685
691
  try {
686
- pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
687
- log.info('Found existing package.json, merging...');
692
+ const pkgContent = readFileSync(pkgPath, 'utf-8');
693
+ if (!pkgContent.trim()) {
694
+ log.warn('Existing package.json is empty, creating new one.');
695
+ } else {
696
+ pkg = JSON.parse(pkgContent);
697
+ log.info('Found existing package.json, merging...');
698
+ }
688
699
  } catch (e) {
689
- log.warn('Could not parse existing package.json, creating new one.');
700
+ if (e instanceof SyntaxError) {
701
+ log.warn(`Invalid JSON in package.json: ${e.message}. Creating new one.`);
702
+ } else {
703
+ log.warn(`Could not read package.json: ${e.message}. Creating new one.`);
704
+ }
690
705
  }
691
706
  }
692
707