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:
35
packages/csx-custom-elements/package.json
Normal file
35
packages/csx-custom-elements/package.json
Normal 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"
|
||||
}
|
||||
30
packages/csx-custom-elements/rollup.config.js
Normal file
30
packages/csx-custom-elements/rollup.config.js
Normal 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: [
|
||||
|
||||
]
|
||||
};
|
||||
13
packages/csx-custom-elements/src/.babelrc
Normal file
13
packages/csx-custom-elements/src/.babelrc
Normal 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" ]
|
||||
]
|
||||
}
|
||||
1
packages/csx-custom-elements/src/custom-element/index.js
Normal file
1
packages/csx-custom-elements/src/custom-element/index.js
Normal file
@@ -0,0 +1 @@
|
||||
export * from './custom-element'
|
||||
2
packages/csx-custom-elements/src/index.js
Normal file
2
packages/csx-custom-elements/src/index.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './vdom';
|
||||
export * from './custom-element';
|
||||
18
packages/csx-custom-elements/src/vdom/constants.js
Normal file
18
packages/csx-custom-elements/src/vdom/constants.js
Normal 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,
|
||||
};
|
||||
2
packages/csx-custom-elements/src/vdom/index.js
Normal file
2
packages/csx-custom-elements/src/vdom/index.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from "./vnode";
|
||||
export * from "./render";
|
||||
91
packages/csx-custom-elements/src/vdom/render.js
Normal file
91
packages/csx-custom-elements/src/vdom/render.js
Normal 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;
|
||||
}
|
||||
44
packages/csx-custom-elements/src/vdom/vnode.js
Normal file
44
packages/csx-custom-elements/src/vdom/vnode.js
Normal 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;
|
||||
}
|
||||
2850
packages/csx-custom-elements/yarn.lock
Normal file
2850
packages/csx-custom-elements/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user