Skip to content

Commit

Permalink
Merge pull request #5 from nparashar150/setup/babel-webpack
Browse files Browse the repository at this point in the history
Setup babel and webpack for JSX compilation to JS Object
  • Loading branch information
nparashar150 authored Oct 6, 2022
2 parents 7ed9d9b + 6e8c295 commit b0e68d6
Show file tree
Hide file tree
Showing 14 changed files with 289 additions and 212 deletions.
10 changes: 9 additions & 1 deletion .babelrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
{
"presets": ["@babel/preset-env", "@babel/preset-react"]
"presets": ["@babel/preset-env"],
"plugins": [
[
"@babel/plugin-transform-react-jsx",
{
"pragma": "OwnReact.createElement"
}
]
]
}
10 changes: 9 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,15 @@
"react/prop-types": 0,
"indent": ["error", 2],
"linebreak-style": 1,
"quotes": ["error", "double"]
"react/react-in-jsx-scope": "off",
"quotes": ["error", "double"],
"no-unused-vars": [
"error",
{
// Allow unused variables that start with OwnReact
"varsIgnorePattern": "OwnReact"
}
]
},
"parserOptions": {
"ecmaVersion": 2021,
Expand Down
92 changes: 36 additions & 56 deletions lib/createElement.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,66 +7,46 @@ import { styleToString } from "./utils/styleToString";
* @param {object} state
* @returns {HTMLElement}
*/
export const createElement = ({
element,
props,
state,
children,
parentElement,
}) => {
// create a new element
const _htmlElement = document?.createElement(element);

export const createElement = (element, props = {}, ...children) => {
// create a new element with the given tagName
let _htmlElement =
typeof element === "string" ? document?.createElement(element) : element();
// add the props to the element
Object.keys(props)?.map((propName) => {
if (propName.includes("on")) {
// if prop is of event type then add event listener
_htmlElement.addEventListener(propName.slice(2), props[propName]);
}
if (propName.toLowerCase() === "classname" || propName === "class") {
// if prop is className
_htmlElement.setAttribute("class", props[propName]);
}
if (propName.toLowerCase() === "style") {
// if prop is style
_htmlElement.setAttribute("style", styleToString(props[propName]));
}
// rest other propNames
_htmlElement?.setAttribute(propName, props[propName]);
});

// store the state in the element
_htmlElement.state = {};
_htmlElement.state = {
...state,
};

// append child to parent element if parent element is passed as _htmlElement
if (parentElement && parentElement instanceof HTMLElement) {
parentElement.appendChild(_htmlElement);
}

// add the children to the element
if (
(typeof children === "string") |
(typeof children === "number") |
(typeof children === "boolean") |
(typeof children === "undefined") |
(children === null)
) {
_htmlElement.innerHTML = children;
} else {
children?.map((child) => {
createElement({
element: child?.element,
props: child?.props,
state: child?.state,
children: child?.children,
parentElement: _htmlElement,
});
if (props && typeof props === "object" && Object.keys(props).length > 0) {
Object.keys(props)?.map((propName) => {
if (propName.includes("on")) {
// if prop is of event type then add event listener
_htmlElement.addEventListener(
propName.slice(2).toLowerCase(),
props[propName]
);
} else if (propName.toLowerCase() === "classname") {
// if prop is className
_htmlElement.setAttribute("class", props[propName]);
} else if (propName.toLowerCase() === "style") {
// if prop is style
_htmlElement.setAttribute("style", styleToString(props[propName]));
} else {
// rest other propNames
_htmlElement?.setAttribute(propName, props[propName]);
}
});
}

children?.map((child) => {
if (
(typeof child === "string") |
(typeof child === "number") |
(typeof child === "boolean") |
(typeof child === "undefined") |
(child === null)
) {
_htmlElement.innerHTML = child;
} else {
_htmlElement.appendChild(child);
}
});

// return the most top-level element
return _htmlElement;
};
Expand Down
11 changes: 11 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { createElement } from "./createElement";
import { styleToString } from "./utils/styleToString";
import { render } from "./render";

const OwnReact = {
createElement,
styleToString,
render,
};

export default OwnReact;
9 changes: 9 additions & 0 deletions lib/render.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
*
* @param {HTMLElement} element
* @param {String} containerId
*/
export const render = (element, containerId) => {
const root = document.getElementById(containerId);
root.appendChild(element);
};
2 changes: 1 addition & 1 deletion nodemon.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[
{
"watch": ["./src", "./server"],
"watch": ["./src", "./lib"],
"ext": ["js", "jsx", "json", "ts", "tsx", "css", "scss"],
"ignore": [
"dist",
Expand Down
11 changes: 8 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,22 @@
"repository": "https://github.com/nparashar150/own-react-lib",
"author": "nparashar150 <[email protected]>",
"scripts": {
"dev": "webpack-dev-server --mode=development",
"start": "webpack --mode=development",
"build": "webpack --mode=production",
"start": "webpack --mode=development",
"dev": "webpack-dev-server --mode=development",
"babel": "nodemon --watch ./src ./scripts/babel-webpack-compile.js",
"lint": "eslint \"src/**/*.{js,jsx}\" \"lib/**/*.{js,jsx}\"",
"lint:fix": "eslint \"src/**/*.{js,jsx}\" \"lib/**/*.{js,jsx}\" --fix"
"lint:fix": "eslint \"src/**/*.{js,jsx}\" \"lib/**/*.{js,jsx}\" --fix",
"babel-webpack-dev": "concurrently \"yarn babel\" \"yarn dev\""
},
"license": "MIT",
"devDependencies": {
"@babel/cli": "^7.19.3",
"@babel/core": "^7.19.1",
"@babel/plugin-transform-react-jsx": "^7.19.0",
"@babel/preset-env": "^7.19.1",
"@babel/preset-react": "^7.18.6",
"babel-loader": "^8.2.5",
"concurrently": "^7.4.0",
"css-loader": "^6.7.1",
"eslint": "^8.23.1",
Expand Down
2 changes: 1 addition & 1 deletion public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<link rel="stylesheet" href="./css/styles.css">
<title>Document</title>
</head>
<body>
<body id="root">
</body>
<script async defer src="./js/own-react-bundle.js"></script>
<script async defer src="./js/useState.js"></script>
Expand Down
2 changes: 1 addition & 1 deletion public/js/own-react-bundle.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions src/components/button/button.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.__btn {
cursor: pointer;
font-weight: 600;
font-size: 1.25rem;
outline-offset: 1px;
padding: 1.25rem 3rem;
border-radius: 0.5rem;
border: 1px solid #1a1a1a;
outline: 1px solid transparent;
transition: all 0.375s ease-in-out;
}

.__btn:hover,
.__btn:focus {
color: #fafafa;
outline-offset: 1px;
border: 1px solid #fafafa;
background-color: #1a1a1a;
outline: 1px solid #1a1a1a;
}
33 changes: 8 additions & 25 deletions src/components/button/button.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,11 @@
import { createElement } from "../../../lib/createElement";
import OwnReact from "../../../lib/index";
import "./button.css";

export const button = (parentElement, props, innerText) => {
if (!parentElement) return;

// styling in JS object is converted to CSS string
const buttonStyles = {
backgroundColor: "#EEE",
color: "#1a1a1a",
padding: "10px",
border: "none",
borderRadius: "5px",
cursor: "pointer",
const Button = (children) => {
const handleClick = () => {
alert("Button clicked");
};

const button = createElement({
element: "button",
props: {
...props,
style: buttonStyles,
},
state: {},
children: innerText,
parentElement,
});

return button;
return <button className="__btn" onClick={() => handleClick()}>{children}</button>;
};

export default Button;
125 changes: 16 additions & 109 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,111 +1,18 @@
import { createElement } from "../lib/createElement";
import { button } from "./components/button/button";
import OwnReact from "../lib/index";
import Button from "./components/button/button";

(function createDOMNode() {
const root = document.body;
function handleOnClick() {
alert("You have clicked twice!!");
}
const divCreatedFromFunction = createElement({
// elementType
element: "div",
// props
props: {
id: "root",
className: "root",
ondblclick: handleOnClick,
style: "text-align: center;",
},
state: {
// state
name: "John Doe",
},
children: [
// children
{
element: "pre", // elementType
props: {
// props
className: "heading",
},
state: {
// state
name: "John Doe's child",
},
children: [
// children
{
// elementType
element: "h1",
props: {
// props
className: "heading",
},
state: {
// state
name: "John Doe's child",
},
// children
children: "This is compiled under webpack",
},
],
},
],
parentElement: root,
});

// creating element inside element created from createElement function
createElement({
// elementType
element: "div",
// props
props: { id: "nestedElement", className: "nestedElement" },
state: {
// state
name: "John Doe",
},
children: [
// children
{
element: "pre", // elementType
props: {
// props
className: "heading",
},
state: {
// state
name: "John Doe's child",
},
children: [
// children
{
// elementType
element: "h1",
props: {
// props
className: "heading",
},
state: {
// state
name: "John Doe's child",
},
// children
children: "Wow!! it supports nested Creation also",
},
],
},
],
parentElement: divCreatedFromFunction,
});

button(
root,
{
onclick: () => {
alert("You have clicked me!!");
},
},
"Click Me"
const App = () => {
return (
<div id="root2">
<Button>Click me</Button>
<h1>My First Own React App</h1>
<p>
<div className="testing">
<h1>My First Own React App with custom Babel and Webpack config</h1>
<p>This is another nesting level</p>
</div>
</p>
</div>
);
})();
export { createElement };
};
OwnReact.render(App(), "root");
Loading

0 comments on commit b0e68d6

Please sign in to comment.