Initial version to monorepo-setup to start experimenting with, featuring a fork of @babel JSX-transformation, and a crude VDOM>DOM rendering-step. The Custom-Elements part is just a placeholder at this point but ready to be populated with base-classes and decorators.

This commit is contained in:
2019-10-21 23:22:25 +02:00
commit 8ae591810a
23 changed files with 10101 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
{
"name": "csx-ce",
"version": "0.0.1",
"dependencies": {},
"devDependencies": {
"@babel/cli": "latest",
"@babel/core": "^7.6.2",
"@babel/plugin-proposal-class-properties": "latest",
"@babel/plugin-proposal-decorators": "latest",
"@babel/plugin-proposal-export-default-from": "latest",
"@babel/plugin-proposal-export-namespace-from": "latest",
"@babel/plugin-proposal-nullish-coalescing-operator": "latest",
"@babel/plugin-proposal-optional-chaining": "latest",
"@babel/plugin-proposal-private-methods": "latest",
"@babel/preset-env": "latest",
"jsdoc": "latest",
"rollup": "latest",
"rollup-plugin-babel": "latest",
"rollup-plugin-node-resolve": "latest",
"rollup-plugin-commonjs": "latest",
"rollup-plugin-terser": "latest",
"rollup-plugin-json": "latest",
"npm-run-all": "latest"
},
"scripts": {
"build": "npm-run-all -p build-cjs build-es6",
"watch": "npm-run-all -p watch-cjs watch-es6",
"build-cjs": "rollup -c",
"watch-cjs": "rollup -c -w",
"build-es6": "npx babel ./src --out-dir=lib --source-maps",
"watch-es6": "npx babel ./src --out-dir=lib --source-maps -w"
},
"module": "./lib/index.js",
"main": "./dist/index.js"
}

View File

@@ -0,0 +1,30 @@
import babel from 'rollup-plugin-babel';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import { terser } from 'rollup-plugin-terser';
import json from "rollup-plugin-json";
// `npm run build` -> `production` is true
// `npm run dev` -> `production` is false
const production = !process.env.ROLLUP_WATCH;
export default {
input: 'src/index.js',
output: {
file: 'dist/index.js',
format: 'cjs', // immediately-invoked function expression — suitable for <script> tags
sourcemap: true
},
plugins: [
json(), // Add json support (sadly in rollup we have to do this explicity, despite the NodeJS algorithm supporitng this by defulat
babel(), // babel (the reason we're doing all of this, babel transpiling)
resolve({// node_modules (again we have to add support in rollup for something that is NodeJS default)
}),
commonjs({ // CJS-modules (require-style bundle support, again something rollup doesnt handle by default)
}),
production && terser() // minify, but only in production
],
external: [
]
};

View File

@@ -0,0 +1,13 @@
{
"presets": [
],
"plugins": [
[ "@babel/plugin-proposal-decorators", { "legacy": true }],
[ "@babel/plugin-proposal-class-properties", { "loose": true } ],
[ "@babel/plugin-proposal-private-methods", {"loose": true } ],
[ "@babel/plugin-proposal-optional-chaining" ],
[ "@babel/plugin-proposal-nullish-coalescing-operator" ],
[ "@babel/plugin-proposal-export-namespace-from" ],
[ "@babel/plugin-proposal-export-default-from" ]
]
}

View File

@@ -0,0 +1 @@
export * from './custom-element'

View File

@@ -0,0 +1,2 @@
export * from './vdom';
export * from './custom-element';

View File

@@ -0,0 +1,18 @@
export const VNODE_EXCLUDE = {
[null]: true,
[undefined]: true
};
// Keys of a Element to be set directly rather than using setAttribute
export const VNODEPROP_DIRECT = {
['checked']: true
};
export const VNODEPROP_EXCLUDE_DIRECT = {
['style']: true,
['class']: true,
};
export const VNODEPROP_IGNORE = {
['key']: true,
};

View File

@@ -0,0 +1,2 @@
export * from "./vnode";
export * from "./render";

View File

@@ -0,0 +1,91 @@
import './vnode';
import {
VNODE_EXCLUDE,
VNODEPROP_DIRECT, VNODEPROP_EXCLUDE_DIRECT,
VNODEPROP_IGNORE,
} from "./constants";
// This is copied from the blog sample right now. it should process jsx but it aint what it needs to be
/**
* @typedef {Object} RenderOptions
* @category VDOM
* @property {Element} host - A host element to update to the specified VDOM
* TODO: Other options clearly...
*/
/**
* This exists as a very basic example/test for JSX-to-DOM
* @param {VNode} vnode
* @param {RenderOptions} opts
* @return {Element}
*/
export function render(vnode, opts = {}) {
// Replace how this works into a queue instead of a recursive call, also consider changing JSX to support (changed)="..." notation
let {
/**
* @type {Element}
*/
host
} = opts;
if(VNODE_EXCLUDE[vnode]) return undefined;
console.log(vnode);
if(vnode instanceof Object){
// Type
if(!host) host = document.createElement(vnode.type);
// Props
if (vnode.props) {
if (vnode.props.style && typeof (vnode.props.style) === 'object') {
for (let styleKey in vnode.props.style) {
host.style[ styleKey ] = vnode.props.style[ styleKey ];
}
}
for (let key in vnode.props) {
let val = vnode.props[key];
if(VNODEPROP_IGNORE[key]){
// NO-OP
}else if(VNODEPROP_DIRECT[key]){
host[key] = val;
}else{
if(!VNODEPROP_EXCLUDE_DIRECT[key] && !key.indexOf('-')){
host[key] = val;
}
if (val === false) {
host.removeAttribute(key);
} else if (val === true) {
host.setAttribute(key, "");
} else{
host.setAttribute(key, val);
}
}
}
}
// Children
if (vnode.children) {
let children = vnode.children instanceof Array? vnode.children : [vnode.children];
for(let child of children){
let el = child instanceof Element? child : render(child, {
...opts,
host: undefined
});
if(el!==undefined){
host.appendChild(el);
}
}
}
// TODO figure out how to handle events (its not that easy to create (click)={this.onClick} or something, that is not supporter by the @babel/parser and we'd have to fork it..
// TODO ref-prop (should it only return once all child els are created and appended to the child?!)
// TODO innerHTML, innerText and other tags/props that are trickyer then just mapping value to attribute
}else{
if(!host) host = document.createTextNode(vnode);
}
return host;
}

View File

@@ -0,0 +1,44 @@
/**
* Type of a node, this is usally the string-tag, but when a CustomElement was created using the @CustomElement annotation the class itself may be used
* @typedef {string|null|Component} VNodeType
* @category VDOM
**/
/**
* Properties of a node
* @typedef {Object.<string, any>} VNodeProps
* @category VDOM
**/
/**
* Children of a node
* @typedef {VNode|Element|Array.<VNode|Element>} VNodeChildren
* @category VDOM
**/
/**
* @typedef VNode
* @interface
* @category VDOM
* @property {VNodeType} type - TagName or CustomElement of the html-element
* @property {VNodeProps} props - Properties to set on the element
* @property {VNodeChildren} children - Children of the element
**/
/**
* This exists as a very basic example/test for JSX-to-DOM.
*
* The custom babel-plugin-transform-csx-jsx removes the need for this, only use asVNode when using with the default
* transform-react plugin of babel
*
* @param {VNodeType} type
* @param {VNodeProps} props
* @param {VNodeChildren} children
* @return {VNode}
*/
export function asVNode(type, props, ...children) {
let vnode = {type, props, children};
console.log(vnode);
return vnode;
}

File diff suppressed because it is too large Load Diff