juxscript 1.0.3 → 1.0.5
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/README.md +37 -92
- package/bin/cli.js +57 -56
- package/lib/components/alert.ts +240 -0
- package/lib/components/app.ts +216 -82
- package/lib/components/badge.ts +164 -0
- package/lib/components/barchart.ts +1248 -0
- package/lib/components/button.ts +188 -53
- package/lib/components/card.ts +75 -61
- package/lib/components/chart.ts +17 -15
- package/lib/components/checkbox.ts +199 -0
- package/lib/components/code.ts +66 -152
- package/lib/components/container.ts +104 -208
- package/lib/components/data.ts +1 -3
- package/lib/components/datepicker.ts +226 -0
- package/lib/components/dialog.ts +258 -0
- package/lib/components/docs-data.json +1969 -423
- package/lib/components/dropdown.ts +244 -0
- package/lib/components/element.ts +271 -0
- package/lib/components/fileupload.ts +319 -0
- package/lib/components/footer.ts +37 -18
- package/lib/components/header.ts +53 -33
- package/lib/components/heading.ts +119 -0
- package/lib/components/helpers.ts +34 -0
- package/lib/components/hero.ts +57 -31
- package/lib/components/include.ts +292 -0
- package/lib/components/input.ts +508 -77
- package/lib/components/layout.ts +144 -18
- package/lib/components/list.ts +83 -74
- package/lib/components/loading.ts +263 -0
- package/lib/components/main.ts +43 -17
- package/lib/components/menu.ts +108 -24
- package/lib/components/modal.ts +50 -21
- package/lib/components/nav.ts +60 -18
- package/lib/components/paragraph.ts +111 -0
- package/lib/components/progress.ts +276 -0
- package/lib/components/radio.ts +236 -0
- package/lib/components/req.ts +300 -0
- package/lib/components/script.ts +33 -74
- package/lib/components/select.ts +280 -0
- package/lib/components/sidebar.ts +87 -37
- package/lib/components/style.ts +47 -70
- package/lib/components/switch.ts +261 -0
- package/lib/components/table.ts +47 -24
- package/lib/components/tabs.ts +105 -63
- package/lib/components/theme-toggle.ts +361 -0
- package/lib/components/token-calculator.ts +380 -0
- package/lib/components/tooltip.ts +244 -0
- package/lib/components/view.ts +36 -20
- package/lib/components/write.ts +284 -0
- package/lib/globals.d.ts +21 -0
- package/lib/jux.ts +178 -68
- package/lib/presets/notion.css +521 -0
- package/lib/presets/notion.jux +27 -0
- package/lib/reactivity/state.ts +364 -0
- package/lib/themes/charts.js +126 -0
- package/machinery/compiler.js +126 -38
- package/machinery/generators/html.js +2 -3
- package/machinery/server.js +2 -2
- package/package.json +29 -3
- package/lib/components/import.ts +0 -430
- package/lib/components/node.ts +0 -200
- package/lib/components/reactivity.js +0 -104
- package/lib/components/theme.ts +0 -97
- package/lib/layouts/notion.css +0 -258
- package/lib/styles/base-theme.css +0 -186
- package/lib/styles/dark-theme.css +0 -144
- package/lib/styles/light-theme.css +0 -144
- package/lib/styles/tokens/dark.css +0 -86
- package/lib/styles/tokens/light.css +0 -86
- package/lib/templates/index.juxt +0 -33
- package/lib/themes/dark.css +0 -86
- package/lib/themes/light.css +0 -86
- /package/lib/{styles → presets}/global.css +0 -0
package/machinery/compiler.js
CHANGED
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import esbuild from 'esbuild';
|
|
4
|
-
import { generateDocs } from './doc-generator.js';
|
|
5
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Compile a .jux file to .js and .html
|
|
7
|
+
*
|
|
8
|
+
* @param {string} juxFilePath - Path to the .jux file
|
|
9
|
+
* @param {Object} options - Compilation options
|
|
10
|
+
* @param {string} options.distDir - Output directory
|
|
11
|
+
* @param {string} options.projectRoot - Project root directory
|
|
12
|
+
* @param {boolean} options.isServe - Whether serving for development
|
|
13
|
+
* @returns {Promise<{jsOutputPath: string, htmlOutputPath: string}>}
|
|
14
|
+
*/
|
|
6
15
|
export async function compileJuxFile(juxFilePath, options = {}) {
|
|
7
16
|
const { distDir, projectRoot, isServe = false } = options;
|
|
8
|
-
|
|
17
|
+
|
|
9
18
|
const relativePath = path.relative(projectRoot, juxFilePath);
|
|
10
19
|
const parsedPath = path.parse(relativePath);
|
|
11
|
-
|
|
20
|
+
|
|
12
21
|
// Output paths
|
|
13
22
|
const outputDir = path.join(distDir, parsedPath.dir);
|
|
14
23
|
const jsOutputPath = path.join(outputDir, `${parsedPath.name}.js`);
|
|
@@ -27,17 +36,17 @@ export async function compileJuxFile(juxFilePath, options = {}) {
|
|
|
27
36
|
// Calculate depth for relative paths
|
|
28
37
|
const depth = parsedPath.dir.split(path.sep).filter(p => p).length;
|
|
29
38
|
const libPath = depth === 0 ? './lib/jux.js' : '../'.repeat(depth) + 'lib/jux.js';
|
|
30
|
-
const styleBasePath = depth === 0 ? './lib/
|
|
39
|
+
const styleBasePath = depth === 0 ? './lib/presets/' : '../'.repeat(depth) + 'lib/presets/';
|
|
31
40
|
|
|
32
41
|
// Transform imports
|
|
33
42
|
let transformedContent = juxContent;
|
|
34
|
-
|
|
43
|
+
|
|
35
44
|
// Replace common import patterns with calculated path
|
|
36
45
|
transformedContent = transformedContent.replace(
|
|
37
46
|
/from\s+['"]\.\.?\/lib\/jux\.js['"]/g,
|
|
38
47
|
`from '${libPath}'`
|
|
39
48
|
);
|
|
40
|
-
|
|
49
|
+
|
|
41
50
|
// Only inject import if:
|
|
42
51
|
// 1. File is not empty (ignoring whitespace and comments)
|
|
43
52
|
// 2. File uses 'jux.' but has no import statement
|
|
@@ -45,11 +54,11 @@ export async function compileJuxFile(juxFilePath, options = {}) {
|
|
|
45
54
|
.replace(/\/\*[\s\S]*?\*\//g, '') // Remove block comments
|
|
46
55
|
.replace(/\/\/.*/g, '') // Remove line comments
|
|
47
56
|
.trim();
|
|
48
|
-
|
|
57
|
+
|
|
49
58
|
const hasContent = contentWithoutComments.length > 0;
|
|
50
59
|
const usesJux = /\bjux\./g.test(contentWithoutComments);
|
|
51
60
|
const hasImport = /import\s+.*from/.test(transformedContent);
|
|
52
|
-
|
|
61
|
+
|
|
53
62
|
if (hasContent && usesJux && !hasImport) {
|
|
54
63
|
transformedContent = `import { jux } from '${libPath}';\n\n${transformedContent}`;
|
|
55
64
|
}
|
|
@@ -61,28 +70,19 @@ export async function compileJuxFile(juxFilePath, options = {}) {
|
|
|
61
70
|
|
|
62
71
|
// Generate HTML with correct script path
|
|
63
72
|
const scriptPath = `./${parsedPath.name}.js`;
|
|
64
|
-
|
|
73
|
+
|
|
65
74
|
const html = `<!DOCTYPE html>
|
|
66
75
|
<html lang="en">
|
|
67
76
|
<head>
|
|
68
77
|
<meta charset="UTF-8">
|
|
69
78
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
70
79
|
<title>${parsedPath.name}</title>
|
|
71
|
-
|
|
72
80
|
<!-- JUX Core Styles -->
|
|
73
|
-
<link rel="stylesheet" href="${styleBasePath}tokens/dark.css">
|
|
74
81
|
<link rel="stylesheet" href="${styleBasePath}global.css">
|
|
75
82
|
</head>
|
|
76
|
-
<body data-theme="
|
|
83
|
+
<body data-theme="">
|
|
77
84
|
<!-- App container -->
|
|
78
85
|
<div id="app" data-jux-page="${parsedPath.name}"></div>
|
|
79
|
-
|
|
80
|
-
<!-- Main content -->
|
|
81
|
-
<div id="appmain"></div>
|
|
82
|
-
|
|
83
|
-
<!-- Modal overlay -->
|
|
84
|
-
<div id="appmodal" aria-hidden="true" role="dialog"></div>
|
|
85
|
-
|
|
86
86
|
<script type="module" src="${scriptPath}"></script>
|
|
87
87
|
${isServe ? `
|
|
88
88
|
<!-- Hot reload -->
|
|
@@ -107,10 +107,16 @@ export async function compileJuxFile(juxFilePath, options = {}) {
|
|
|
107
107
|
return { jsOutputPath, htmlOutputPath };
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Copy and build the JUX library from TypeScript to JavaScript
|
|
112
|
+
*
|
|
113
|
+
* @param {string} projectRoot - Root directory containing lib/
|
|
114
|
+
* @param {string} distDir - Destination directory for built files
|
|
115
|
+
*/
|
|
110
116
|
export async function copyLibToOutput(projectRoot, distDir) {
|
|
111
117
|
// Simplified lib path resolution
|
|
112
118
|
const libSrc = path.resolve(projectRoot, '../lib');
|
|
113
|
-
|
|
119
|
+
|
|
114
120
|
if (!fs.existsSync(libSrc)) {
|
|
115
121
|
throw new Error(`lib/ directory not found at ${libSrc}`);
|
|
116
122
|
}
|
|
@@ -129,7 +135,7 @@ export async function copyLibToOutput(projectRoot, distDir) {
|
|
|
129
135
|
|
|
130
136
|
// Find all TypeScript entry points
|
|
131
137
|
const tsFiles = findFiles(libSrc, '.ts');
|
|
132
|
-
|
|
138
|
+
|
|
133
139
|
if (tsFiles.length === 0) {
|
|
134
140
|
console.warn('⚠️ No TypeScript files found in lib/');
|
|
135
141
|
return;
|
|
@@ -168,50 +174,123 @@ export async function copyLibToOutput(projectRoot, distDir) {
|
|
|
168
174
|
console.log('✅ Library ready\n');
|
|
169
175
|
}
|
|
170
176
|
|
|
177
|
+
/**
|
|
178
|
+
* Copy project assets (CSS, JS, images) from jux/ to dist/
|
|
179
|
+
*
|
|
180
|
+
* @param {string} projectRoot - Source directory (jux/)
|
|
181
|
+
* @param {string} distDir - Destination directory (jux-dist/)
|
|
182
|
+
*/
|
|
171
183
|
export async function copyProjectAssets(projectRoot, distDir) {
|
|
172
184
|
console.log('📦 Copying project assets...');
|
|
173
|
-
|
|
185
|
+
|
|
174
186
|
// Find all CSS and JS files in project root (excluding node_modules, dist, .git)
|
|
175
187
|
const allFiles = [];
|
|
176
188
|
findProjectFiles(projectRoot, ['.css', '.js'], allFiles, projectRoot);
|
|
177
|
-
|
|
189
|
+
|
|
178
190
|
console.log(` Found ${allFiles.length} asset file(s)`);
|
|
179
|
-
|
|
191
|
+
|
|
180
192
|
for (const srcPath of allFiles) {
|
|
181
193
|
const relativePath = path.relative(projectRoot, srcPath);
|
|
182
194
|
const destPath = path.join(distDir, relativePath);
|
|
183
195
|
const destDir = path.dirname(destPath);
|
|
184
|
-
|
|
196
|
+
|
|
185
197
|
// Create destination directory if needed
|
|
186
198
|
if (!fs.existsSync(destDir)) {
|
|
187
199
|
fs.mkdirSync(destDir, { recursive: true });
|
|
188
200
|
}
|
|
189
|
-
|
|
201
|
+
|
|
190
202
|
// Copy file
|
|
191
203
|
fs.copyFileSync(srcPath, destPath);
|
|
192
204
|
console.log(` ✓ ${relativePath}`);
|
|
193
205
|
}
|
|
194
|
-
|
|
206
|
+
|
|
195
207
|
console.log('✅ Project assets copied\n');
|
|
196
208
|
}
|
|
197
209
|
|
|
210
|
+
/**
|
|
211
|
+
* Transpile TypeScript files from jux/ to jux-dist/, preserving folder structure
|
|
212
|
+
*
|
|
213
|
+
* @param {string} srcDir - Source directory (jux/)
|
|
214
|
+
* @param {string} destDir - Destination directory (jux-dist/)
|
|
215
|
+
* @example
|
|
216
|
+
* // jux/samples/mypage.ts -> jux-dist/samples/mypage.js
|
|
217
|
+
* await transpileProjectTypeScript('jux/', 'jux-dist/');
|
|
218
|
+
*/
|
|
219
|
+
export async function transpileProjectTypeScript(srcDir, destDir) {
|
|
220
|
+
console.log('🔷 Transpiling TypeScript files...');
|
|
221
|
+
|
|
222
|
+
// Find all TypeScript files in the project
|
|
223
|
+
const tsFiles = findFiles(srcDir, '.ts');
|
|
224
|
+
|
|
225
|
+
if (tsFiles.length === 0) {
|
|
226
|
+
console.log(' No TypeScript files found in project');
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
console.log(` Found ${tsFiles.length} TypeScript file(s)`);
|
|
231
|
+
|
|
232
|
+
try {
|
|
233
|
+
// Build all TypeScript files with esbuild
|
|
234
|
+
await esbuild.build({
|
|
235
|
+
entryPoints: tsFiles,
|
|
236
|
+
bundle: false,
|
|
237
|
+
format: 'esm',
|
|
238
|
+
outdir: destDir,
|
|
239
|
+
outbase: srcDir,
|
|
240
|
+
platform: 'browser',
|
|
241
|
+
target: 'es2020',
|
|
242
|
+
loader: {
|
|
243
|
+
'.ts': 'ts'
|
|
244
|
+
},
|
|
245
|
+
logLevel: 'warning'
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
// Log each transpiled file
|
|
249
|
+
tsFiles.forEach(tsFile => {
|
|
250
|
+
const relativePath = path.relative(srcDir, tsFile);
|
|
251
|
+
const jsPath = relativePath.replace(/\.ts$/, '.js');
|
|
252
|
+
console.log(` ✓ ${relativePath} → ${jsPath}`);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
console.log('✅ TypeScript transpiled\n');
|
|
256
|
+
|
|
257
|
+
} catch (err) {
|
|
258
|
+
console.error('❌ Failed to transpile TypeScript:', err.message);
|
|
259
|
+
throw err;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Recursively find files with a specific extension
|
|
265
|
+
*
|
|
266
|
+
* @param {string} dir - Directory to search
|
|
267
|
+
* @param {string} extension - File extension (e.g., '.ts')
|
|
268
|
+
* @param {string[]} fileList - Accumulator for found files
|
|
269
|
+
* @returns {string[]} Array of file paths
|
|
270
|
+
*/
|
|
198
271
|
function findFiles(dir, extension, fileList = []) {
|
|
199
272
|
const files = fs.readdirSync(dir);
|
|
200
|
-
|
|
273
|
+
|
|
201
274
|
files.forEach(file => {
|
|
202
275
|
const filePath = path.join(dir, file);
|
|
203
276
|
const stat = fs.statSync(filePath);
|
|
204
|
-
|
|
277
|
+
|
|
205
278
|
if (stat.isDirectory()) {
|
|
206
279
|
findFiles(filePath, extension, fileList);
|
|
207
280
|
} else if (file.endsWith(extension)) {
|
|
208
281
|
fileList.push(filePath);
|
|
209
282
|
}
|
|
210
283
|
});
|
|
211
|
-
|
|
284
|
+
|
|
212
285
|
return fileList;
|
|
213
286
|
}
|
|
214
287
|
|
|
288
|
+
/**
|
|
289
|
+
* Copy non-TypeScript files (CSS, JSON, JS, SVG, etc.)
|
|
290
|
+
*
|
|
291
|
+
* @param {string} src - Source directory
|
|
292
|
+
* @param {string} dest - Destination directory
|
|
293
|
+
*/
|
|
215
294
|
function copyNonTsFiles(src, dest) {
|
|
216
295
|
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
217
296
|
|
|
@@ -226,23 +305,32 @@ function copyNonTsFiles(src, dest) {
|
|
|
226
305
|
copyNonTsFiles(srcPath, destPath);
|
|
227
306
|
} else if (entry.isFile()) {
|
|
228
307
|
const ext = path.extname(entry.name);
|
|
229
|
-
// Copy CSS, JSON, and JS files (but not .ts files)
|
|
230
|
-
if (
|
|
308
|
+
// Copy CSS, JSON, SVG, and JS files (but not .ts files)
|
|
309
|
+
if (['.css', '.json', '.js', '.svg', '.png', '.jpg', '.jpeg', '.gif', '.webp'].includes(ext)) {
|
|
231
310
|
fs.copyFileSync(srcPath, destPath);
|
|
232
|
-
console.log(` → Copied: ${path.relative(src, srcPath)}`);
|
|
233
311
|
}
|
|
234
312
|
}
|
|
235
313
|
}
|
|
236
314
|
}
|
|
237
315
|
|
|
238
|
-
|
|
316
|
+
/**
|
|
317
|
+
* Find project files with specific extensions, excluding certain directories
|
|
318
|
+
*
|
|
319
|
+
* @param {string} dir - Directory to search
|
|
320
|
+
* @param {string[]} extensions - File extensions to find
|
|
321
|
+
* @param {string[]} fileList - Accumulator for found files
|
|
322
|
+
* @param {string} rootDir - Root directory for relative paths
|
|
323
|
+
* @param {string[]} excludeDirs - Directories to exclude
|
|
324
|
+
* @returns {string[]} Array of file paths
|
|
325
|
+
*/
|
|
326
|
+
function findProjectFiles(dir, extensions, fileList = [], rootDir = dir, excludeDirs = ['node_modules', 'jux-dist', '.git', 'lib']) {
|
|
239
327
|
if (!fs.existsSync(dir)) return fileList;
|
|
240
|
-
|
|
328
|
+
|
|
241
329
|
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
242
|
-
|
|
330
|
+
|
|
243
331
|
for (const entry of entries) {
|
|
244
332
|
const fullPath = path.join(dir, entry.name);
|
|
245
|
-
|
|
333
|
+
|
|
246
334
|
if (entry.isDirectory()) {
|
|
247
335
|
// Skip excluded directories
|
|
248
336
|
if (excludeDirs.includes(entry.name)) {
|
|
@@ -257,6 +345,6 @@ function findProjectFiles(dir, extensions, fileList = [], rootDir = dir, exclude
|
|
|
257
345
|
}
|
|
258
346
|
}
|
|
259
347
|
}
|
|
260
|
-
|
|
348
|
+
|
|
261
349
|
return fileList;
|
|
262
350
|
}
|
|
@@ -42,8 +42,7 @@ export function generateHTML(fileName, options = {}) {
|
|
|
42
42
|
<title>${fileName}</title>
|
|
43
43
|
|
|
44
44
|
<!-- JUX Core Styles -->
|
|
45
|
-
<link rel="stylesheet" href="${prefix}lib/
|
|
46
|
-
<link rel="stylesheet" href="${prefix}lib/styles/global.css">
|
|
45
|
+
<link rel="stylesheet" href="${prefix}lib/presets/global.css">
|
|
47
46
|
</head>
|
|
48
47
|
<body data-theme="dark">
|
|
49
48
|
${appStructure}
|
|
@@ -61,7 +60,7 @@ ${appStructure}
|
|
|
61
60
|
*/
|
|
62
61
|
function buildAppStructure(pageName) {
|
|
63
62
|
const page = pageName || 'index';
|
|
64
|
-
|
|
63
|
+
|
|
65
64
|
return ` <!-- App Container -->
|
|
66
65
|
<div id="app" data-jux-page="${page}">
|
|
67
66
|
<!-- Header -->
|
package/machinery/server.js
CHANGED
|
@@ -186,7 +186,7 @@ async function initDatabase() {
|
|
|
186
186
|
}
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
-
export async function start(port = 3000
|
|
189
|
+
export async function start(port = 3000) {
|
|
190
190
|
await initDatabase();
|
|
191
|
-
return serve(port,
|
|
191
|
+
return serve(port, './jux-dist'); // Changed default
|
|
192
192
|
}
|
package/package.json
CHANGED
|
@@ -1,23 +1,49 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "juxscript",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A JavaScript UX authorship platform",
|
|
6
6
|
"main": "lib/jux.js",
|
|
7
|
-
"types": "
|
|
7
|
+
"types": "lib/jux.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./lib/jux.d.ts",
|
|
11
|
+
"import": "./lib/jux.js",
|
|
12
|
+
"default": "./lib/jux.js"
|
|
13
|
+
},
|
|
14
|
+
"./lib/*": "./lib/*",
|
|
15
|
+
"./lib/components/*": "./lib/components/*",
|
|
16
|
+
"./package.json": "./package.json"
|
|
17
|
+
},
|
|
18
|
+
"typesVersions": {
|
|
19
|
+
"*": {
|
|
20
|
+
"*": [
|
|
21
|
+
"lib/*"
|
|
22
|
+
],
|
|
23
|
+
"lib/*": [
|
|
24
|
+
"lib/*"
|
|
25
|
+
],
|
|
26
|
+
"lib/components/*": [
|
|
27
|
+
"lib/components/*"
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
},
|
|
8
31
|
"bin": {
|
|
9
32
|
"jux": "./bin/cli.js"
|
|
10
33
|
},
|
|
11
34
|
"scripts": {
|
|
12
35
|
"dev": "cd examples && npx jux serve",
|
|
13
36
|
"build:examples": "cd examples && rm -rf dist && npx jux build",
|
|
14
|
-
"
|
|
37
|
+
"build": "tsc",
|
|
38
|
+
"test": "node test/run-tests.js",
|
|
39
|
+
"generate:icons": "node scripts/generate-icon-types.js"
|
|
15
40
|
},
|
|
16
41
|
"files": [
|
|
17
42
|
"lib",
|
|
18
43
|
"bin",
|
|
19
44
|
"machinery",
|
|
20
45
|
"types",
|
|
46
|
+
"lib/**/*.d.ts",
|
|
21
47
|
"README.md",
|
|
22
48
|
"LICENSE"
|
|
23
49
|
],
|