This commit is contained in:
CoolElectronics 2023-12-31 22:01:48 -05:00
commit 26f12e0a8f
No known key found for this signature in database
GPG key ID: F63593D168636C50
12 changed files with 972 additions and 0 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
examples/lib/
dist/*
node_modules

2
.npmignore Normal file
View file

@ -0,0 +1,2 @@
examples/
node_modules

23
AliceJS.d.ts vendored Normal file
View file

@ -0,0 +1,23 @@
declare namespace JSX {
export type IntrinsicElements = { [index: string]: any };
}
declare function h(
type: string,
props: { [index: string]: any } | null,
...children: (HTMLElement | string)[]
): Node;
type AliceJSReferenceSink = { readonly __symbol: unique symbol };
declare function use(sink: any, mapping?: (...args: any[]) => any): AliceJSReferenceSink;
type Stateful<T> = T & { readonly symbol: unique symbol };
declare function stateful<T>(target: T): Stateful<T>;
declare function handle(references: AliceJSReferenceSink, callback: (value: any) => void): void;
declare function css(strings: TemplateStringsArray, ...values: any): string;
declare var styled: { new: typeof css };

466
AliceJS.js Normal file
View file

@ -0,0 +1,466 @@
// The global list of "references", as captured by the proxy in stateful
let __reference_stack = [];
// We add some extra properties into various objects throughout, better to use symbols and not interfere
let ALICEJS_REFERENCES_MAPPING = Symbol();
let ALICEJS_REFERENCES_MARKER = Symbol();
let ALICEJS_STATEFUL_LISTENERS = Symbol();
// Say you have some code like
//// let state = stateful({
//// a: 1
//// })
//// let elm = <p>{window.use(state.a)}</p>
//
// According to the standard, the order of events is as follows:
// - the getter for window.use gets called, setting __reference_stack to an empty list
// - the proxy for state.a is triggered, pushing { state, "a", Proxy(state) } onto __reference_stack
// - the function that the getter returns is called, popping everything off the stack
// - the JSX factory h() is now passed the *reference* of state.a, not the value
Object.defineProperty(window, "use", {
get: () => {
__reference_stack = [];
return (_sink, mapping) => {
let references = __reference_stack;
__reference_stack = [];
references[ALICEJS_REFERENCES_MARKER] = true;
if (mapping) references[ALICEJS_REFERENCES_MAPPING] = mapping;
return references;
};
}
});
Object.assign(window, { h, stateful, handle, css, styled: { new: css } });
// This wraps the target in a proxy, doing 2 things:
// - whenever a property is accessed, update the reference stack
// - whenever a property is set, notify the subscribed listeners
// This is what makes our "pass-by-reference" magic work
export function stateful(target) {
target[ALICEJS_STATEFUL_LISTENERS] = [];
const proxy = new Proxy(target, {
get(target, property, proxy) {
__reference_stack.push({ target, property, proxy });
return Reflect.get(target, property, proxy);
},
set(target, property, val) {
for (const listener of target[ALICEJS_STATEFUL_LISTENERS]) {
listener(target, property, val);
}
return Reflect.set(target, property, val);
},
});
return proxy;
}
function isAJSReferences(arr) {
return arr instanceof Array && ALICEJS_REFERENCES_MARKER in arr
}
// This lets you subscribe to a stateful object
export function handle(references, callback) {
if (!isAJSReferences(references))
throw new Error("Not an AliceJS reference set!");
if (ALICEJS_REFERENCES_MAPPING in references) {
const mapping = references[ALICEJS_REFERENCES_MAPPING];
const used_props = [];
const used_targets = [];
const values = new Map();
const pairs = [];
const partial_update = (target, prop, val) => {
if (used_props.includes(prop) && used_targets.includes(target)) {
values.get(target)[prop] = val;
}
};
const full_update = () => {
const flattened_values = pairs.map(
(pair) => values.get(pair[0])[pair[1]],
);
const value = mapping(...flattened_values);
callback(value);
};
for (const p of references) {
const target = p.target;
const prop = p.property;
used_props.push(prop);
used_targets.push(target);
pairs.push([target, prop]);
if (!values.has(target)) {
values.set(target, {});
}
partial_update(target, prop, target[prop]);
target[ALICEJS_STATEFUL_LISTENERS].push((t, p, v) => {
partial_update(t, p, v);
full_update();
});
}
full_update();
} else {
const reference = references[references.length - 1];
const subscription = (target, prop, val) => {
if (prop === reference.property && target === reference.target) {
callback(val);
}
};
reference.target[ALICEJS_STATEFUL_LISTENERS].push(subscription);
subscription(reference.target, reference.property, reference.target[reference.property]);
}
}
// Actual JSX factory. Responsible for creating the HTML elements and all of the *reactive* syntactic sugar
export function h(type, props, ...children) {
if (typeof type === "function") {
let newthis = stateful({});
let component = type.bind(newthis);
return component();
}
const elm = document.createElement(type);
function addChild(child) {
if (isAJSReferences(child)) {
let appended = [];
handle(child, (val) => {
if (appended.length > 1) {
// this is why we don't encourage arrays (jank)
appended.forEach(n => n.remove());
appended = addChild(val);
} else if (appended.length > 0) {
appended[0].replaceWith((appended = addChild(val))[0]);
} else {
appended = addChild(val);
}
});
} else if (child instanceof Node) {
elm.appendChild(child);
return [child];
} else if (child instanceof Array) {
let elms = [];
for (const childchild of child) {
elms = elms.concat(addChild(childchild));
}
return elms;
} else {
let node = document.createTextNode(child);
elm.appendChild(node);
return [node];
}
}
for (const child of children) {
addChild(child);
}
if (!props) return elm;
function useProp(name, callback) {
if (!(name in props)) return;
let prop = props[name];
callback(prop);
delete props[name];
}
// insert an element at the start
useProp("before", callback => {
addChild(callback());
})
useProp("css", classname => {
elm.classList.add(classname);
elm.classList.add("self");
});
// if/then/else syntax
useProp("if", condition => {
let thenblock = props["then"];
let elseblock = props["else"];
if (isAJSReferences(condition)) {
if (thenblock) elm.appendChild(thenblock);
if (elseblock) elm.appendChild(elseblock);
handle(condition, val => {
if (thenblock) {
if (val) {
thenblock.style.display = "";
if (elseblock) elseblock.style.display = "none";
} else {
thenblock.style.display = "none";
if (elseblock) elseblock.style.display = "";
}
} else {
if (val) {
elm.style.display = "";
} else {
elm.style.display = "none";
}
}
});
} else {
if (thenblock) {
if (condition) {
elm.appendChild(thenblock);
} else if (elseblock) {
elm.appendChild(elseblock);
}
} else {
if (condition) {
elm.appendChild(thenblock);
} else if (elseblock) {
elm.appendChild(elseblock);
} else {
elm.style.display = "none";
return document.createTextNode("");
}
}
}
delete props["then"];
delete props["else"];
});
if ("for" in props && "do" in props) {
const predicate = props["for"];
const closure = props["do"];
if (isAJSReferences(predicate)) {
const __elms = [];
let lastpredicate = [];
handle(predicate, val => {
if (
Object.keys(val).length &&
Object.keys(val).length == lastpredicate.length
) {
let i = 0;
for (const index in val) {
if (
deepEqual(val[index], lastpredicate[index])
) {
continue;
}
const part = closure(val[index], index, val);
elm.replaceChild(part, __elms[i]);
__elms[i] = part;
i += 1;
}
lastpredicate = Object.keys(
JSON.parse(JSON.stringify(val)),
);
} else {
for (const part of __elms) {
part.remove();
}
for (const index in val) {
const value = val[index];
const part = closure(value, index, val);
if (part instanceof HTMLElement) {
__elms.push(part);
elm.appendChild(part);
}
}
lastpredicate = [];
}
});
} else {
for (const index in predicate) {
const value = predicate[index];
const part = closure(value, index, predicate);
if (part instanceof Node) elm.appendChild(part);
}
}
delete props["for"];
delete props["do"];
}
// two-way bind an <input>
useProp("$value", references => {
if (!isAJSReferences(references)) return;
if (!(elm instanceof HTMLInputElement)) return;
handle(references, value => elm.value = value);
let reference = references[references.length - 1];
elm.addEventListener("change", () => {
reference.proxy[reference.property] = elm.value;
})
});
// insert an element at the end
useProp("after", callback => {
addChild(callback());
})
// apply the non-reactive properties
for (const name in props) {
const prop = props[name];
if (isAJSReferences(prop)) {
handle(prop, (val) => {
JSXAddAttributes(elm, name, val);
});
} else {
JSXAddAttributes(elm, name, prop);
}
}
return elm;
}
// Where properties are assigned to elements, and where the *non-reactive* syntax sugar goes
function JSXAddAttributes(elm, name, prop) {
if (name === "class") {
elm.className = prop;
return;
}
if (typeof prop === "function" && name === "@mount") {
prop(elm);
return;
}
if (typeof prop === "function" && name.startsWith("#")) {
const names = name.substring(1);
for (const name of names.split("$")) {
elm.addEventListener(name, (...args) => {
window.$el = elm;
prop(...args);
});
}
return;
}
if (typeof prop === "function" && name.startsWith("observe")) {
const observerclass = window[`${name.substring(8)}Observer`];
if (!observerclass) {
console.error(`Observer ${name} does not exist`);
return;
}
const observer = new observerclass(entries => {
for (const entry of entries) {
window.$el = elm;
prop(entry);
}
});
observer.observe(elm);
return;
}
if (name.startsWith("bind:")) {
const propname = name.substring(5);
prop[propname] = elm;
return;
}
elm.setAttribute(name, prop);
}
function parse_css(uid, css) {
let cssParsed = "";
const virtualDoc = document.implementation.createHTMLDocument("");
const virtualStyleElement = document.createElement("style");
virtualStyleElement.textContent = css;
virtualDoc.body.appendChild(virtualStyleElement);
//@ts-ignore
for (const rule of virtualStyleElement.sheet.cssRules) {
rule.selectorText = rule.selectorText.includes("self")
? `.${uid}.self${rule.selectorText.replace("self", "")}`
: `.${uid} ${rule.selectorText}`;
cssParsed += `${rule.cssText}\n`;
}
return cssParsed;
}
export function css(strings, ...values) {
const uid = `alicecss-${Array(16)
.fill(0)
.map(() => {
return Math.floor(Math.random() * 16).toString(16);
})
.join("")}`;
const styleElement = document.createElement("style");
document.head.appendChild(styleElement);
const flattened_template = [];
for (const i in strings) {
flattened_template.push(strings[i]);
if (values[i]) {
const prop = values[i];
if (isAJSReferences(prop)) {
const current_i = flattened_template.length;
handle(prop, (val) => {
flattened_template[current_i] = String(val);
styleElement.textContent = parse_css(
uid,
flattened_template.join(""),
);
});
} else {
flattened_template.push(String(prop));
}
}
}
styleElement.textContent = parse_css(
uid,
flattened_template.join(""),
);
return uid;
}
function deepEqual(object1, object2) {
const keys1 = Object.keys(object1);
const keys2 = Object.keys(object2);
if (keys1.length !== keys2.length) {
return false;
}
for (const key of keys1) {
const val1 = object1[key];
const val2 = object2[key];
const areObjects = isObject(val1) && isObject(val2);
if (
(areObjects && !deepEqual(val1, val2)) ||
(!areObjects && val1 !== val2)
) {
return false;
}
}
return true;
}
function isObject(object) {
return object != null && typeof object === "object";
}

7
LICENSE Normal file
View file

@ -0,0 +1,7 @@
Copyright 2024 Mercury Workshop
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

86
README.md Normal file
View file

@ -0,0 +1,86 @@
# AliceJS
A utilitarian rendering library
## What is AliceJS
AliceJS is a reactive JSX-based library with **no virtual dom**
## Why do we need another javascript framework????
not sure to be honest
## What does it look like?
Here's a simple counter app
```jsx
function App() {
this.counter = 0;
return (
<div>
<button #click={() => this.counter++} >Click me!</button>
<p>
Value: {use(this.counter)}
</p>
</div>
);
}
window.addEventListener("load", () => {
document.body.appendChild(<App/>);
});
```
Compare that to the equivalent code in react:
```jsx
import { React, useState } from 'react'
function App() {
const [counter, setCounter] = useState(0);
const increase = () => {
setCounter(count => count + 1);
};
return (
<div>
<button onClick={increase}>Click me!</button>
<p>
Value: {use(this.counter)}
</p>
</div>
);
}
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById("root")
);
```
AliceJS provides a simple and intuitive API at a low cost
To get started with AliceJS, add this to your `tsconfig.json`
```json
"jsx":"react",
"jsxFactory":"h",
"jsxFragmentFactory":"YOU_CANT_USE_FRAGMENTS",
"types": ["@MercuryWorkshop/AliceJS"],
```
and run `npm install @mercuryworkshop/alicejs`
If you prefer using modules and are using a bundler, simply `import "@mercuryworkshop/alicejs";` into at least one file you're using.
If you don't like using modules, just add `<script src="://unpkg.com/@mercuryworkshop/alicejs"></script>` to your html, and you can use AliceJS as normal.
AliceJS can even be used without a build step, here's the counter example in plain JS
```javascript
function Index() {
this.counter = 0;
return (h("div",{},
h("button", { "#click": () => this.counter++ }, "Click me!"),
h("p",{}, "Value: ", use(this.counter))));
}
window.addEventListener("load", () => {
document.body.appendChild(h(Index, null));
});
```

18
examples/example.html Normal file
View file

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>AliceJS examples</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="index.css" />
<script src="../dist/index.js"></script>
<script src="lib/index.js"></script>
</head>
<body>
</body>
</html>

14
examples/index.css Normal file
View file

@ -0,0 +1,14 @@
html,body {
padding: 0;
margin: 0;
width: 100vw;
height: 100vh;
background-color: #191724;
}
body {
display: flex;
justify-content: center;
align-items: center;
}

41
examples/index.tsx Normal file
View file

@ -0,0 +1,41 @@
function Index() {
let css = styled.new`
self {
background-color: #1f1d2e;
border-radius: 25px;
padding:2em;
}
button {
border-radius: 25px;
}
p,h1 {
font-family: "serif";
color: #e0def4;
}
p {
font-size:15px;
}
`;
this.counter = 0;
return (
<div css={css}>
<h1>AliceJS Examples</h1>
<button #click={() => this.counter++} >Click me!</button>
<p>
Value: {use(this.counter)}
</p>
<p>
is {use(this.counter)} odd? {use(this.counter, p => p % 2 == 1)}
</p>
</div>
);
}
window.addEventListener("load", () => {
document.body.appendChild(<Index />);
});

24
package.json Normal file
View file

@ -0,0 +1,24 @@
{
"name": "@mercuryworkshop/alicejs",
"version": "1.0.0",
"description": "A utilitarian HTML rendering library",
"scripts": {
"build": "esbuild --minify --bundle AliceJS.js --outdir=dist && tsc",
"watch": "esbuild --watch=forever --bundle AliceJS.js --outdir=dist & tsc --watch"
},
"keywords": ["html","jsx","framework","alicejs"],
"author": "MercuryWorkshop",
"repository": "https://github.com/MercuryWorkshop/AliceJS",
"license": "MIT",
"exports": {
".": {
"browser": "./dist/index.js",
"node": "./dist/index.js",
"types":"./AliceJS.d.ts"
}
},
"devDependencies": {
"esbuild": "^0.19.11",
"typescript": "^5.3.3"
}
}

259
pnpm-lock.yaml generated Normal file
View file

@ -0,0 +1,259 @@
lockfileVersion: '6.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
devDependencies:
esbuild:
specifier: ^0.19.11
version: 0.19.11
typescript:
specifier: ^5.3.3
version: 5.3.3
packages:
/@esbuild/aix-ppc64@0.19.11:
resolution: {integrity: sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g==}
engines: {node: '>=12'}
cpu: [ppc64]
os: [aix]
requiresBuild: true
dev: true
optional: true
/@esbuild/android-arm64@0.19.11:
resolution: {integrity: sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q==}
engines: {node: '>=12'}
cpu: [arm64]
os: [android]
requiresBuild: true
dev: true
optional: true
/@esbuild/android-arm@0.19.11:
resolution: {integrity: sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw==}
engines: {node: '>=12'}
cpu: [arm]
os: [android]
requiresBuild: true
dev: true
optional: true
/@esbuild/android-x64@0.19.11:
resolution: {integrity: sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg==}
engines: {node: '>=12'}
cpu: [x64]
os: [android]
requiresBuild: true
dev: true
optional: true
/@esbuild/darwin-arm64@0.19.11:
resolution: {integrity: sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ==}
engines: {node: '>=12'}
cpu: [arm64]
os: [darwin]
requiresBuild: true
dev: true
optional: true
/@esbuild/darwin-x64@0.19.11:
resolution: {integrity: sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g==}
engines: {node: '>=12'}
cpu: [x64]
os: [darwin]
requiresBuild: true
dev: true
optional: true
/@esbuild/freebsd-arm64@0.19.11:
resolution: {integrity: sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA==}
engines: {node: '>=12'}
cpu: [arm64]
os: [freebsd]
requiresBuild: true
dev: true
optional: true
/@esbuild/freebsd-x64@0.19.11:
resolution: {integrity: sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw==}
engines: {node: '>=12'}
cpu: [x64]
os: [freebsd]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-arm64@0.19.11:
resolution: {integrity: sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg==}
engines: {node: '>=12'}
cpu: [arm64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-arm@0.19.11:
resolution: {integrity: sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q==}
engines: {node: '>=12'}
cpu: [arm]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-ia32@0.19.11:
resolution: {integrity: sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA==}
engines: {node: '>=12'}
cpu: [ia32]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-loong64@0.19.11:
resolution: {integrity: sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg==}
engines: {node: '>=12'}
cpu: [loong64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-mips64el@0.19.11:
resolution: {integrity: sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg==}
engines: {node: '>=12'}
cpu: [mips64el]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-ppc64@0.19.11:
resolution: {integrity: sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA==}
engines: {node: '>=12'}
cpu: [ppc64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-riscv64@0.19.11:
resolution: {integrity: sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ==}
engines: {node: '>=12'}
cpu: [riscv64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-s390x@0.19.11:
resolution: {integrity: sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q==}
engines: {node: '>=12'}
cpu: [s390x]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-x64@0.19.11:
resolution: {integrity: sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA==}
engines: {node: '>=12'}
cpu: [x64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/netbsd-x64@0.19.11:
resolution: {integrity: sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ==}
engines: {node: '>=12'}
cpu: [x64]
os: [netbsd]
requiresBuild: true
dev: true
optional: true
/@esbuild/openbsd-x64@0.19.11:
resolution: {integrity: sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw==}
engines: {node: '>=12'}
cpu: [x64]
os: [openbsd]
requiresBuild: true
dev: true
optional: true
/@esbuild/sunos-x64@0.19.11:
resolution: {integrity: sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ==}
engines: {node: '>=12'}
cpu: [x64]
os: [sunos]
requiresBuild: true
dev: true
optional: true
/@esbuild/win32-arm64@0.19.11:
resolution: {integrity: sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ==}
engines: {node: '>=12'}
cpu: [arm64]
os: [win32]
requiresBuild: true
dev: true
optional: true
/@esbuild/win32-ia32@0.19.11:
resolution: {integrity: sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg==}
engines: {node: '>=12'}
cpu: [ia32]
os: [win32]
requiresBuild: true
dev: true
optional: true
/@esbuild/win32-x64@0.19.11:
resolution: {integrity: sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw==}
engines: {node: '>=12'}
cpu: [x64]
os: [win32]
requiresBuild: true
dev: true
optional: true
/esbuild@0.19.11:
resolution: {integrity: sha512-HJ96Hev2hX/6i5cDVwcqiJBBtuo9+FeIJOtZ9W1kA5M6AMJRHUZlpYZ1/SbEwtO0ioNAW8rUooVpC/WehY2SfA==}
engines: {node: '>=12'}
hasBin: true
requiresBuild: true
optionalDependencies:
'@esbuild/aix-ppc64': 0.19.11
'@esbuild/android-arm': 0.19.11
'@esbuild/android-arm64': 0.19.11
'@esbuild/android-x64': 0.19.11
'@esbuild/darwin-arm64': 0.19.11
'@esbuild/darwin-x64': 0.19.11
'@esbuild/freebsd-arm64': 0.19.11
'@esbuild/freebsd-x64': 0.19.11
'@esbuild/linux-arm': 0.19.11
'@esbuild/linux-arm64': 0.19.11
'@esbuild/linux-ia32': 0.19.11
'@esbuild/linux-loong64': 0.19.11
'@esbuild/linux-mips64el': 0.19.11
'@esbuild/linux-ppc64': 0.19.11
'@esbuild/linux-riscv64': 0.19.11
'@esbuild/linux-s390x': 0.19.11
'@esbuild/linux-x64': 0.19.11
'@esbuild/netbsd-x64': 0.19.11
'@esbuild/openbsd-x64': 0.19.11
'@esbuild/sunos-x64': 0.19.11
'@esbuild/win32-arm64': 0.19.11
'@esbuild/win32-ia32': 0.19.11
'@esbuild/win32-x64': 0.19.11
dev: true
/typescript@5.3.3:
resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==}
engines: {node: '>=14.17'}
hasBin: true
dev: true

29
tsconfig.json Normal file
View file

@ -0,0 +1,29 @@
{
"compilerOptions": {
"lib": [
"ESNext",
"dom"
],
"outDir": "./examples/lib",
"removeComments": true,
"target": "ES6",
"jsx":"react",
"jsxFactory":"h",
"jsxFragmentFactory":"YOU_CANT_USE_FRAGMENTS",
"sourceMap": true,
"sourceRoot": "",
"alwaysStrict": false,
"noImplicitAny": false,
"strictNullChecks":false,
"noUncheckedIndexedAccess": true
},
"include": ["./examples/*.ts","./examples/*.tsx", "./AliceJS.d.ts"],
"exclude": [
"node_modules/**/*"
]
}