This commit lays the foundation for migrating OxJS from its custom module
system to ES modules while maintaining backward compatibility.
Key changes:
- Set up npm project with Vite for modern build tooling
- Created ES module versions of core Ox utilities (Type, Collection, DOM, etc.)
- Implemented compatibility layer for legacy Ox.load() pattern
- Added Vitest for testing with initial test suite
- Created script to extract existing inline tests from documentation
- Updated .gitignore for Node.js/npm development
The migration preserves OxJS's innovative inline test system and maintains
backward compatibility. Original source files remain unchanged.
Next steps include migrating UI modules, replacing the Python build script,
and creating npm package distribution.
🤖 Generated with AI assistance
137 lines
No EOL
3.8 KiB
JavaScript
137 lines
No EOL
3.8 KiB
JavaScript
import { defineConfig } from 'vite';
|
|
import { resolve } from 'path';
|
|
import legacy from '@vitejs/plugin-legacy';
|
|
import { glob } from 'glob';
|
|
import fs from 'fs';
|
|
|
|
// Helper to get all Ox core modules
|
|
function getOxModules() {
|
|
const files = glob.sync('source/Ox/js/*.js');
|
|
const entry = {};
|
|
files.forEach(file => {
|
|
const name = file.replace('source/Ox/js/', '').replace('.js', '');
|
|
entry[`ox/${name}`] = resolve(__dirname, file);
|
|
});
|
|
return entry;
|
|
}
|
|
|
|
export default defineConfig({
|
|
build: {
|
|
lib: {
|
|
entry: {
|
|
// Main entry points
|
|
'ox': resolve(__dirname, 'source/Ox.js'),
|
|
'ox.ui': resolve(__dirname, 'source/UI/UI.js'),
|
|
'ox.geo': resolve(__dirname, 'source/Geo/Geo.js'),
|
|
'ox.image': resolve(__dirname, 'source/Image/Image.js'),
|
|
'ox.unicode': resolve(__dirname, 'source/Unicode/Unicode.js'),
|
|
// Individual Ox modules for tree-shaking
|
|
...getOxModules()
|
|
},
|
|
name: 'Ox',
|
|
formats: ['es', 'umd', 'iife']
|
|
},
|
|
rollupOptions: {
|
|
output: {
|
|
globals: {
|
|
// Define any external dependencies here
|
|
},
|
|
assetFileNames: (assetInfo) => {
|
|
if (assetInfo.name === 'style.css') {
|
|
return 'ox.css';
|
|
}
|
|
return assetInfo.name;
|
|
}
|
|
}
|
|
},
|
|
sourcemap: true,
|
|
minify: 'terser',
|
|
outDir: 'dist'
|
|
},
|
|
resolve: {
|
|
alias: {
|
|
'@': resolve(__dirname, './source'),
|
|
'Ox': resolve(__dirname, './source/Ox'),
|
|
'UI': resolve(__dirname, './source/UI'),
|
|
}
|
|
},
|
|
server: {
|
|
port: 3000,
|
|
open: '/examples/'
|
|
},
|
|
plugins: [
|
|
legacy({
|
|
targets: ['defaults', 'not IE 11']
|
|
}),
|
|
{
|
|
name: 'ox-theme-processor',
|
|
async buildStart() {
|
|
// Process theme files similar to Python build script
|
|
await processThemes();
|
|
}
|
|
}
|
|
],
|
|
test: {
|
|
globals: true,
|
|
environment: 'jsdom',
|
|
setupFiles: './test/test-setup.js'
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Process OxJS themes (replaces Python theme processing)
|
|
*/
|
|
async function processThemes() {
|
|
const themesDir = resolve(__dirname, 'source/UI/themes');
|
|
const themes = fs.readdirSync(themesDir).filter(d =>
|
|
fs.statSync(resolve(themesDir, d)).isDirectory() && !d.startsWith('.')
|
|
);
|
|
|
|
for (const theme of themes) {
|
|
const themeJsonPath = resolve(themesDir, theme, 'json/theme.jsonc');
|
|
if (fs.existsSync(themeJsonPath)) {
|
|
// Parse JSONC (JSON with comments)
|
|
const jsonc = fs.readFileSync(themeJsonPath, 'utf-8');
|
|
const json = jsonc.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, '');
|
|
const themeData = JSON.parse(json);
|
|
|
|
// Process theme CSS
|
|
const themeCssPath = resolve(__dirname, 'source/UI/css/theme.css');
|
|
if (fs.existsSync(themeCssPath)) {
|
|
let css = fs.readFileSync(themeCssPath, 'utf-8');
|
|
|
|
// Replace theme variables
|
|
css = css.replace(/\$(\w+)(\[\d+\])?/g, (match, key, index) => {
|
|
const value = themeData[key];
|
|
if (!value) return match;
|
|
|
|
if (index) {
|
|
const idx = parseInt(index.slice(1, -1));
|
|
return formatColorValue(value[idx]);
|
|
}
|
|
return formatColorValue(value);
|
|
});
|
|
|
|
// Write processed theme CSS
|
|
const outputDir = resolve(__dirname, `dist/themes/${theme}/css`);
|
|
fs.mkdirSync(outputDir, { recursive: true });
|
|
fs.writeFileSync(resolve(outputDir, 'theme.css'), css);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function formatColorValue(value) {
|
|
if (typeof value === 'string') {
|
|
return value;
|
|
}
|
|
if (Array.isArray(value)) {
|
|
if (Array.isArray(value[0])) {
|
|
// Multiple color values
|
|
return value.map(v => `rgb(${v.join(', ')})`).join(', ');
|
|
}
|
|
// Single color value
|
|
return `rgb${value.length === 4 ? 'a' : ''}(${value.join(', ')})`;
|
|
}
|
|
return value;
|
|
} |