New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

battuta

Package Overview
Dependencies
Maintainers
0
Versions
37
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

battuta

a sketchy experimental frontend framework highly inspired from [solidjs](https://www.solidjs.com/) and [solid-three](https://github.com/solidjs-community/solid-three)

0.0.15-modeless7
npm
Version published
Weekly downloads
18
-89.02%
Maintainers
0
Weekly downloads
 
Created
Source

Battuta

a sketchy experimental frontend framework highly inspired from solidjs and solid-three

Setup a new project

Web: npx battuta init

then run it with npm run dev

Table of Contents

JSX

JSX expressions are compiled differently based on the type of tag used

DOM

This expression:

<div style:color={color()}>
    {value()}
</div>

Transforms to:

createElement("div")
    [assign](() => color(), "style", "color")
    [append](() => value())

Components

Given

function Component(props) {
    return <div>{props.value}</div>
}

This expression:

<Component value={value()}>

Transforms to:

Component({ get value() { return value() } })

Constructors

Given

class A {
    prop = 0;
    constructor(arg_2);
    constructor(arg_1, arg_2, arg_3) {}
}

Those expressions:

<A arg_2={value_2()} prop={value_3()}>
<A arg_2={value_2()} arg_3={value_4()} prop={value_3()}>

Transform to:

A[create](value_2())
    [assign](() => value_3(), "prop")
A[create](undefined, value_2(), value_4())
    [assign](() => value_3(), "prop")

The props names are matched with the args names

Functions

Given

function F(first: string, second: number) {}

Those expressions:

<F first={value_1()} second={value_2()}>
<F second={value_2()} prop={value_3()}>

Transform to:

F(value_1(), value_2())
F(undefined, value_2())
    [assign](() => value_3(), "prop")

for this to work some methods need to be implemented on the parent prototypes, by default Object instances define default implementations that can be overwriten, at least insert and remove need to be implemented

this is an example in the case of threejs

import { append, remove, childrenIndex, empty } from "battuta/runtime";
import { Object3D, Group } from "three";

// required 
Object3D.prototype[insert] = function(child: any, index?: number){
    this.add(child);
    return this;
}

// required 
Object3D.prototype[remove] = function(){
    this.removeFromParent();
    return this;
}

// not needed if the childrens order doesn't matter 
Object3D.prototype[childrenIndex] = function(child){
    return this.children.indexOf(child);
}

// not needed if the childrens order doesn't matter 
Object3D.prototype[empty] = function(){
    return new Group();
}

// implemented by default, can be overwriten
Object3D.prototype[create] = function (...props) {
    return Reflect.construct(this as any, props);
}

// implemented by default, can be overwriten
Object3D.prototype[set] = function (value, ...keys) {
    const key = keys.pop()!;
    resolveObj(this, keys)[key] = value;
    return this;
}

// implemented by default, can be overwriten
Object3D.prototype[assign] = function (value, ...keys) {
    const key = keys.pop()!;
    const target = resolveObj(this, keys);
    useEffect(() => target[key] = value());
    return this;
}

// implemented by default, can be overwriten
Object3D.prototype[call] = function (value, ...keys) {
    const key = keys.pop()!;
    const target = resolveObj(this, keys);
    const f = target[key].bind(target);
    useEffect(() => f(...value()));
    return this;
}

Contexts

like other frameworks it also support contexts

const [ useValue, ValueProvider ] = createContext((props) => {
    const [ getValue, setValue ] = createSignal();

    return {
        getValue,
        setValue,
    }
})

function App() {
    return <ValueProvider>
        <Component/>
    </ValueProvider>
}

const [ useEvents, EventsProvider ] = createContext(() => new EventTarget());

function Component() {

    const { getValue, setValue } = useValue();

    const child1 = <Child/>
    const child2 = () => <Child/>

    return <EventsProvider>
        <Child/> {/* run inside the EventsProvider */}
        {child1} {/* run outside the EventsProvider */}
        {child2} {/* run inside the EventsProvider */}
    <EventsProvider>
}

CLI

battuta init create a new empty project
battuta bundle use vite to bundle the app
battuta dev open the vite dev server
battuta compile <file> transform the given file
battuta compile:jsx <file> transform the given file's jsx expressions
battuta optimize <file> run the optimization steps (no terser minification)
battuta optimize:strings <file>
battuta optimize:functions <file>

Use with vite

As the framework is mostly a vite wrapper you can also use it with vite directly, or by part.

Vite plugins

All in one plugin

the default export of battuta/vite is a plugin containing all the plugins as well as the default vite config


import battutaPlugin from "battuta/vite";

export default defineConfig({
    plugins: [
        // optional config
        battutaPlugin({
            // options for the bun macros plugin
            macros: Options,
            root: "src/main.tsx",
            optimizer: {
                strings: true,
                functions: true,
            },
        })
    ]
})

sources

JSX

the battutaJSX plugin handle the JSX transformations


import { battutaJSX, battutaInferModes } from "battuta/vite";

export default defineConfig({
    plugins: [
        battutaInferModes(),
        battutaJSX()
    ]
})

sources

Optimizer

battuta mostly use the terser integration in vite to optimize and minify builds, the battutaOptimizer act as a preparation step before terser to help improve the build.


import { battutaOptimizer } from "battuta/vite";

export default defineConfig({
    plugins: [
        battutaOptimizer({
            strings: true,
            functions: true,
        })
    ]
})

the strings optimizer catch all string duplicates in the codebase (happens a lot with JSX) and merge them in const declarations which can be minified

the functions optimizer raise function definitions to the highest scope it can reach, for example

this piece of code:

function doSomething(arg) {
    return [
        () => args
            .filter(x => x > 10)
            .map(x => x ** 2)
            .filter(x => x < 1000)
            .forEach(x => console.log(x)),
        () => false
    ]
}

becomes this:

const f1 = x => x > 10;
const f2 = x => x ** 2;
const f3 = x => x < 1000;
const f4 = x => console.log(x);
const f5 = () => false;

function doSomething(arg) {
    return [
        () => args
            .filter(f1)
            .map(f2)
            .filter(f3)
            .forEach(f4),
        f5
    ]
}

I have no idea if this may break some libs or if it has any benefit, but I wanned to try that

sources

Macros

the battutaMacros plugin is a simple fork of unplugin-macros exposing the AST to the macro and allowing it to inject raw js code. checkout the css macro for an example


import { battutaMacros } from "battuta/vite";

export default defineConfig({
    plugins: [
        battutaMacros()
    ]
})

sources

Virtual Root

the battutaVirtualRoot plugin create the index.html file, for now it just allow to remove it from the repo


import { battutaVirtualRoot } from "battuta/vite";

export default defineConfig({
    plugins: [
        battutaVirtualRoot()
    ]
})

sources

Folders

the battutaFolders plugin moves the content of the .temp to the .dist folder during the build


import { battutaFolders } from "battuta/vite";

export default defineConfig({
    plugins: [
        battutaFolders()
    ]
})

sources

Config

the battutaConfig export contain the default config plugin


import { battutaConfig } from "battuta/vite";

export default defineConfig({
    plugins: [
        battutaConfig()
    ]
})

sources

Transformation APIs

CLI actions are also available from javascript

import { compile, transformJSX } from "battuta/compiler";
import { optimize, optimizeStrings } from "battuta/optimizer";

const { code } = transformJSX(`
    <div></div>
`);

FAQs

Package last updated on 18 Feb 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts