@unsetsoft/ryunixjs 0.2.6-alpha.8 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,25 +1,25 @@
1
- # RyunixJS
2
-
3
- ## What is RyunixJS?
4
-
5
- Is a ReactJS Clone! Even lighter, however, at a very early stage for production use.
6
-
7
- ## Install & Usage
8
-
9
- `npm install @unsetsoft/create-ryunix-app -g`
10
-
11
- ### Obtain and download the template
12
-
13
- `create-ryunix-app get`
14
-
15
- ### Rename your final folder
16
-
17
- `create-ryunix-app get --dirname awasome-ryunix-app`
18
-
19
- ## Bugs?
20
-
21
- You can create an issue on GitHub.
22
-
23
- ## Do you want to contribute?
24
-
1
+ # RyunixJS
2
+
3
+ ## What is RyunixJS?
4
+
5
+ Is a ReactJS Clone! Even lighter, however, at a very early stage for production use.
6
+
7
+ ## Install & Usage
8
+
9
+ `npm install @unsetsoft/create-ryunix-app -g`
10
+
11
+ ### Obtain and download the template
12
+
13
+ `create-ryunix-app get`
14
+
15
+ ### Rename your final folder
16
+
17
+ `create-ryunix-app get --dirname awasome-ryunix-app`
18
+
19
+ ## Bugs?
20
+
21
+ You can create an issue on GitHub.
22
+
23
+ ## Do you want to contribute?
24
+
25
25
  Fork a send a pull request!
@@ -0,0 +1,6 @@
1
+ // Can be imported from webpack package
2
+ const webpack = require("webpack");
3
+ const webpackConfig = require("../webpack.config.js");
4
+ const compiler = webpack(webpackConfig);
5
+
6
+ module.exports = { compiler };
package/bin/index.js CHANGED
@@ -2,6 +2,8 @@
2
2
  const yargs = require("yargs");
3
3
  const { hideBin } = require("yargs/helpers");
4
4
  const { server } = require("./serve");
5
+ const { compiler } = require("./compiler");
6
+ const logger = require("terminal-log");
5
7
  const serv = {
6
8
  command: "server",
7
9
  describe: "Run server",
@@ -9,4 +11,27 @@ const serv = {
9
11
  await server.start();
10
12
  },
11
13
  };
12
- yargs(hideBin(process.argv)).command(serv).parse();
14
+
15
+ const build = {
16
+ command: "build",
17
+ describe: "Run builder",
18
+ handler: async (arg) => {
19
+ compiler.run((err, stats) => {
20
+ if (err || stats.hasErrors()) {
21
+ // ...
22
+ logger.error(err);
23
+ }
24
+
25
+ logger.ok("Deployment completed");
26
+
27
+ compiler.close((closeErr) => {
28
+ if (closeErr) {
29
+ // ...
30
+ logger.error(closeErr);
31
+ }
32
+ });
33
+ });
34
+ },
35
+ };
36
+
37
+ yargs(hideBin(process.argv)).command(serv).command(build).parse();
package/bin/serve.js CHANGED
@@ -1,9 +1,9 @@
1
- const Webpack = require("webpack");
2
- const WebpackDevServer = require("webpack-dev-server");
3
- const webpackConfig = require("../webpack.config.js");
4
-
5
- const compiler = Webpack(webpackConfig);
6
- const devServerOptions = { ...webpackConfig.devServer, open: true };
7
- const server = new WebpackDevServer(devServerOptions, compiler);
8
-
9
- module.exports = { server };
1
+ const Webpack = require("webpack");
2
+ const WebpackDevServer = require("webpack-dev-server");
3
+ const webpackConfig = require("../webpack.config.js");
4
+
5
+ const compiler = Webpack(webpackConfig);
6
+ const devServerOptions = { ...webpackConfig.devServer, open: true };
7
+ const server = new WebpackDevServer(devServerOptions, compiler);
8
+
9
+ module.exports = {server};
package/lib/dom.js CHANGED
@@ -1,491 +1,491 @@
1
- /**
2
- * The function creates a new element with the given type, props, and children.
3
- * @param type - The type of the element to be created, such as "div", "span", "h1", etc.
4
- * @param props - The `props` parameter is an object that contains the properties or attributes of the
5
- * element being created. These properties can include things like `className`, `id`, `style`, and any
6
- * other custom attributes that the user wants to add to the element. The `props` object is spread
7
- * using the spread
8
- * @param children - The `children` parameter is a rest parameter that allows the function to accept
9
- * any number of arguments after the `props` parameter. These arguments will be treated as children
10
- * elements of the created element. The `map` function is used to iterate over each child and create a
11
- * new element if it is not
12
- * @returns A JavaScript object with a `type` property and a `props` property. The `type` property is
13
- * set to the `type` argument passed into the function, and the `props` property is an object that
14
- * includes any additional properties passed in the `props` argument, as well as a `children` property
15
- * that is an array of any child elements passed in the `...children` argument
16
- */
17
- function createElement(type, props, ...children) {
18
- return {
19
- type,
20
- props: {
21
- ...props,
22
- children: children
23
- .flat()
24
- .map((child) =>
25
- typeof child === "object" ? child : createTextElement(child)
26
- ),
27
- },
28
- };
29
- }
30
-
31
- /**
32
- * The function creates a text element with a given text value.
33
- * @param text - The text content that will be used to create a new text element.
34
- * @returns A JavaScript object with a `type` property set to `"TEXT_ELEMENT"` and a `props` property
35
- * that contains a `nodeValue` property set to the `text` parameter and an empty `children` array.
36
- */
37
- function createTextElement(text) {
38
- return {
39
- type: "TEXT_ELEMENT",
40
- props: {
41
- nodeValue: text,
42
- children: [],
43
- },
44
- };
45
- }
46
-
47
- /**
48
- * The function creates a new DOM element based on the given fiber object and updates its properties.
49
- * @param fiber - The fiber parameter is an object that represents a node in the fiber tree. It
50
- * contains information about the element type, props, and children of the node.
51
- * @returns The `createDom` function returns a newly created DOM element based on the `fiber` object
52
- * passed as an argument. If the `fiber` object represents a text element, a text node is created using
53
- * `document.createTextNode("")`. Otherwise, a new element is created using
54
- * `document.createElement(fiber.type)`. The function then calls the `updateDom` function to update the
55
- * properties of the newly created
56
- */
57
- function createDom(fiber) {
58
- const dom =
59
- fiber.type == "TEXT_ELEMENT"
60
- ? document.createTextNode("")
61
- : document.createElement(fiber.type);
62
-
63
- updateDom(dom, {}, fiber.props);
64
-
65
- return dom;
66
- }
67
-
68
- const isEvent = (key) => key.startsWith("on");
69
- const isProperty = (key) => key !== "children" && !isEvent(key);
70
- const isNew = (prev, next) => (key) => prev[key] !== next[key];
71
- const isGone = (prev, next) => (key) => !(key in next);
72
-
73
- /**
74
- * The function updates the DOM by removing old event listeners and properties, and adding new ones
75
- * based on the previous and next props.
76
- * @param dom - The DOM element that needs to be updated with new props.
77
- * @param prevProps - An object representing the previous props (properties) of a DOM element.
78
- * @param nextProps - An object containing the new props that need to be updated in the DOM.
79
- */
80
- function updateDom(dom, prevProps, nextProps) {
81
- Object.keys(prevProps)
82
- .filter(isEvent)
83
- .filter((key) => !(key in nextProps) || isNew(prevProps, nextProps)(key))
84
- .forEach((name) => {
85
- const eventType = name.toLowerCase().substring(2);
86
- dom.removeEventListener(eventType, prevProps[name]);
87
- });
88
-
89
- Object.keys(prevProps)
90
- .filter(isProperty)
91
- .filter(isGone(prevProps, nextProps))
92
- .forEach((name) => {
93
- dom[name] = "";
94
- });
95
-
96
- Object.keys(nextProps)
97
- .filter(isProperty)
98
- .filter(isNew(prevProps, nextProps))
99
- .forEach((name) => {
100
- dom[name] = nextProps[name];
101
- });
102
-
103
- Object.keys(nextProps)
104
- .filter(isEvent)
105
- .filter(isNew(prevProps, nextProps))
106
- .forEach((name) => {
107
- const eventType = name.toLowerCase().substring(2);
108
- dom.addEventListener(eventType, nextProps[name]);
109
- });
110
- }
111
-
112
- /**
113
- * The function commits changes made to the virtual DOM to the actual DOM.
114
- */
115
- function commitRoot() {
116
- deletions.forEach(commitWork);
117
- commitWork(wipRoot.child);
118
- currentRoot = wipRoot;
119
- wipRoot = null;
120
- }
121
-
122
- /**
123
- * The function cancels all effect hooks in a given fiber.
124
- * @param fiber - The "fiber" parameter is likely referring to a data structure used in React.js to
125
- * represent a component and its state. It contains information about the component's props, state, and
126
- * children, as well as metadata used by React to manage updates and rendering. The function
127
- * "cancelEffects" is likely intended
128
- */
129
- function cancelEffects(fiber) {
130
- if (fiber.hooks) {
131
- fiber.hooks
132
- .filter((hook) => hook.tag === "effect" && hook.cancel)
133
- .forEach((effectHook) => {
134
- effectHook.cancel();
135
- });
136
- }
137
- }
138
-
139
- /**
140
- * The function runs all effect hooks in a given fiber.
141
- * @param fiber - The "fiber" parameter is likely referring to a data structure used in the
142
- * implementation of a fiber-based reconciliation algorithm, such as the one used in React. A fiber
143
- * represents a unit of work that needs to be performed by the reconciliation algorithm, and it
144
- * contains information about a component and its children, as
145
- */
146
- function runEffects(fiber) {
147
- if (fiber.hooks) {
148
- fiber.hooks
149
- .filter((hook) => hook.tag === "effect" && hook.effect)
150
- .forEach((effectHook) => {
151
- effectHook.cancel = effectHook.effect();
152
- });
153
- }
154
- }
155
-
156
- /**
157
- * The function commits changes made to the DOM based on the effect tag of the fiber.
158
- * @param fiber - A fiber is a unit of work in Ryunix's reconciliation process. It represents a
159
- * component and its state at a particular point in time. The `commitWork` function takes a fiber as a
160
- * parameter to commit the changes made during the reconciliation process to the actual DOM.
161
- * @returns The function does not return anything, it performs side effects by manipulating the DOM.
162
- */
163
- function commitWork(fiber) {
164
- if (!fiber) {
165
- return;
166
- }
167
-
168
- let domParentFiber = fiber.parent;
169
- while (!domParentFiber.dom) {
170
- domParentFiber = domParentFiber.parent;
171
- }
172
- const domParent = domParentFiber.dom;
173
-
174
- if (fiber.effectTag === "PLACEMENT") {
175
- if (fiber.dom != null) {
176
- domParent.appendChild(fiber.dom);
177
- }
178
- runEffects(fiber);
179
- } else if (fiber.effectTag === "UPDATE") {
180
- cancelEffects(fiber);
181
- if (fiber.dom != null) {
182
- updateDom(fiber.dom, fiber.alternate.props, fiber.props);
183
- }
184
- runEffects(fiber);
185
- } else if (fiber.effectTag === "DELETION") {
186
- cancelEffects(fiber);
187
- commitDeletion(fiber, domParent);
188
- return;
189
- }
190
-
191
- commitWork(fiber.child);
192
- commitWork(fiber.sibling);
193
- }
194
-
195
- /**
196
- * The function removes a fiber's corresponding DOM node from its parent node or recursively removes
197
- * its child's DOM node until it finds a node to remove.
198
- * @param fiber - a fiber node in a fiber tree, which represents a component or an element in the Ryunix
199
- * application.
200
- * @param domParent - The parent DOM element from which the fiber's DOM element needs to be removed.
201
- */
202
- function commitDeletion(fiber, domParent) {
203
- if (fiber.dom) {
204
- domParent.removeChild(fiber.dom);
205
- } else {
206
- commitDeletion(fiber.child, domParent);
207
- }
208
- }
209
-
210
- let containerRoot = null;
211
-
212
- /**
213
- * The function creates a root container for a web application.
214
- * @param root - The parameter `root` is likely referring to an HTML element that will serve as the
215
- * root or container for a web application or component. The `createRoot` function takes this element
216
- * as an argument and assigns it to a variable called `containerRoot`. This variable can then be used
217
- * to manipulate the contents
218
- */
219
- function createRoot(root) {
220
- containerRoot = root;
221
- }
222
-
223
- /**
224
- * The function renders an element into a container using a work-in-progress root.
225
- * @param element - The element parameter is the component or element that needs to be rendered in the
226
- * container. It could be a Ryunix component or a DOM element.
227
- * @param container - The container parameter is the DOM element where the rendered element will be
228
- * appended to. this parameter is optional if you use createRoot().
229
- */
230
- function render(element, container) {
231
- wipRoot = {
232
- dom: containerRoot || container,
233
- props: {
234
- children: [element],
235
- },
236
- alternate: currentRoot,
237
- };
238
- deletions = [];
239
- nextUnitOfWork = wipRoot;
240
- }
241
-
242
- let nextUnitOfWork = null;
243
- let currentRoot = null;
244
- let wipRoot = null;
245
- let deletions = null;
246
-
247
- /**
248
- * This function uses requestIdleCallback to perform work on a fiber tree until it is complete or the
249
- * browser needs to yield to other tasks.
250
- * @param deadline - The `deadline` parameter is an object that represents the amount of time the
251
- * browser has to perform work before it needs to handle other tasks. It has a `timeRemaining()` method
252
- * that returns the amount of time remaining before the deadline is reached. The `shouldYield` variable
253
- * is used to determine
254
- */
255
- function workLoop(deadline) {
256
- let shouldYield = false;
257
- while (nextUnitOfWork && !shouldYield) {
258
- nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
259
- shouldYield = deadline.timeRemaining() < 1;
260
- }
261
-
262
- if (!nextUnitOfWork && wipRoot) {
263
- commitRoot();
264
- }
265
-
266
- requestIdleCallback(workLoop);
267
- }
268
-
269
- requestIdleCallback(workLoop);
270
-
271
- /**
272
- * The function performs a unit of work by updating either a function component or a host component and
273
- * returns the next fiber to be processed.
274
- * @param fiber - A fiber is a unit of work in Ryunix that represents a component and its state. It
275
- * contains information about the component's type, props, and children, as well as pointers to its
276
- * parent, child, and sibling fibers. The `performUnitOfWork` function takes a fiber as a parameter and
277
- * performs work
278
- * @returns The function `performUnitOfWork` returns the next fiber to be processed. If the current
279
- * fiber has a child, it returns the child. Otherwise, it looks for the next sibling of the current
280
- * fiber. If there are no more siblings, it goes up the tree to the parent and looks for the next
281
- * sibling of the parent. The function returns `null` if there are no more fibers to process.
282
- */
283
- function performUnitOfWork(fiber) {
284
- const isFunctionComponent = fiber.type instanceof Function;
285
- if (isFunctionComponent) {
286
- updateFunctionComponent(fiber);
287
- } else {
288
- updateHostComponent(fiber);
289
- }
290
- if (fiber.child) {
291
- return fiber.child;
292
- }
293
- let nextFiber = fiber;
294
- while (nextFiber) {
295
- if (nextFiber.sibling) {
296
- return nextFiber.sibling;
297
- }
298
- nextFiber = nextFiber.parent;
299
- }
300
- }
301
-
302
- let wipFiber = null;
303
- let hookIndex = null;
304
-
305
- /**
306
- * This function updates a function component by setting up a work-in-progress fiber, resetting the
307
- * hook index, creating an empty hooks array, rendering the component, and reconciling its children.
308
- * @param fiber - The fiber parameter is an object that represents a node in the fiber tree. It
309
- * contains information about the component, its props, state, and children. In this function, it is
310
- * used to update the state of the component and its children.
311
- */
312
- function updateFunctionComponent(fiber) {
313
- wipFiber = fiber;
314
- hookIndex = 0;
315
- wipFiber.hooks = [];
316
- const children = [fiber.type(fiber.props)];
317
- reconcileChildren(fiber, children);
318
- }
319
-
320
- /**
321
- * This function updates a host component's DOM element and reconciles its children.
322
- * @param fiber - A fiber is a unit of work in Ryunix that represents a component and its state. It
323
- * contains information about the component's type, props, and children, as well as pointers to other
324
- * fibers in the tree.
325
- */
326
- function updateHostComponent(fiber) {
327
- if (!fiber.dom) {
328
- fiber.dom = createDom(fiber);
329
- }
330
- reconcileChildren(fiber, fiber.props.children.flat());
331
- }
332
-
333
- /**
334
- * This function reconciles the children of a fiber node with a new set of elements, creating new
335
- * fibers for new elements, updating existing fibers for elements with the same type, and marking old
336
- * fibers for deletion if they are not present in the new set of elements.
337
- * @param wipFiber - A work-in-progress fiber object representing a component or element in the virtual
338
- * DOM tree.
339
- * @param elements - an array of elements representing the new children to be rendered in the current
340
- * fiber's subtree
341
- */
342
- function reconcileChildren(wipFiber, elements) {
343
- let index = 0;
344
- let oldFiber = wipFiber.alternate && wipFiber.alternate.child;
345
- let prevSibling = null;
346
-
347
- while (index < elements.length || oldFiber != null) {
348
- const element = elements[index];
349
- let newFiber = null;
350
-
351
- const sameType = oldFiber && element && element.type == oldFiber.type;
352
-
353
- if (sameType) {
354
- newFiber = {
355
- type: oldFiber.type,
356
- props: element.props,
357
- dom: oldFiber.dom,
358
- parent: wipFiber,
359
- alternate: oldFiber,
360
- effectTag: "UPDATE",
361
- };
362
- }
363
- if (element && !sameType) {
364
- newFiber = {
365
- type: element.type,
366
- props: element.props,
367
- dom: null,
368
- parent: wipFiber,
369
- alternate: null,
370
- effectTag: "PLACEMENT",
371
- };
372
- }
373
- if (oldFiber && !sameType) {
374
- oldFiber.effectTag = "DELETION";
375
- deletions.push(oldFiber);
376
- }
377
-
378
- if (oldFiber) {
379
- oldFiber = oldFiber.sibling;
380
- }
381
-
382
- if (index === 0) {
383
- wipFiber.child = newFiber;
384
- } else if (element) {
385
- prevSibling.sibling = newFiber;
386
- }
387
-
388
- prevSibling = newFiber;
389
- index++;
390
- }
391
- }
392
-
393
- // Hooks
394
-
395
- /**
396
- * The function creates a state hook for a Ryunix-like framework.
397
- * @param initial - The initial value of the state for the hook.
398
- * @returns The `useStore` function returns an array with two elements: the current state value and a
399
- * `setState` function that can be used to update the state.
400
- */
401
- function useStore(initial) {
402
- const oldHook =
403
- wipFiber.alternate &&
404
- wipFiber.alternate.hooks &&
405
- wipFiber.alternate.hooks[hookIndex];
406
- const hook = {
407
- state: oldHook ? oldHook.state : initial,
408
- queue: [],
409
- };
410
-
411
- const actions = oldHook ? oldHook.queue : [];
412
- actions.forEach((action) => {
413
- hook.state = typeof action === "function" ? action(hook.state) : action;
414
- });
415
-
416
- /**
417
- * The function `setState` updates the state of a component in Ryunix by adding an action to a queue
418
- * and setting up a new work-in-progress root.
419
- * @param action - The `action` parameter is an object that represents a state update to be performed
420
- * on a component. It contains information about the type of update to be performed and any new data
421
- * that needs to be applied to the component's state.
422
- */
423
- const setState = (action) => {
424
- hook.queue.push(action);
425
- wipRoot = {
426
- dom: currentRoot.dom,
427
- props: currentRoot.props,
428
- alternate: currentRoot,
429
- };
430
- nextUnitOfWork = wipRoot;
431
- deletions = [];
432
- };
433
-
434
- wipFiber.hooks.push(hook);
435
- hookIndex++;
436
- return [hook.state, setState];
437
- }
438
-
439
- /**
440
- * The function checks if the previous dependencies are different from the next dependencies.
441
- * @param prevDeps - The previous dependencies, which could be an array of values or objects that a
442
- * function or component depends on.
443
- * @param nextDeps - `nextDeps` is an array of dependencies that are being checked for changes. These
444
- * dependencies are typically used in React's `useEffect` and `useCallback` hooks to determine when a
445
- * component should re-render or when a function should be re-created.
446
- */
447
- const hasDepsChanged = (prevDeps, nextDeps) =>
448
- !prevDeps ||
449
- !nextDeps ||
450
- prevDeps.length !== nextDeps.length ||
451
- prevDeps.some((dep, index) => dep !== nextDeps[index]);
452
-
453
- /**
454
- * This is a function that creates a hook for managing side effects in React components.
455
- * @param effect - The effect function that will be executed after the component has rendered or when
456
- * the dependencies have changed. It can perform side effects such as fetching data, updating the DOM,
457
- * or subscribing to events.
458
- * @param deps - An array of dependencies that the effect depends on. If any of the dependencies change
459
- * between renders, the effect will be re-run. If the array is empty, the effect will only run once on
460
- * mount and never again.
461
- */
462
- function useEffect(effect, deps) {
463
- const oldHook =
464
- wipFiber.alternate &&
465
- wipFiber.alternate.hooks &&
466
- wipFiber.alternate.hooks[hookIndex];
467
-
468
- const hasChanged = hasDepsChanged(oldHook ? oldHook.deps : undefined, deps);
469
-
470
- const hook = {
471
- tag: "effect",
472
- effect: hasChanged ? effect : null,
473
- cancel: hasChanged && oldHook && oldHook.cancel,
474
- deps,
475
- };
476
-
477
- wipFiber.hooks.push(hook);
478
- hookIndex++;
479
- }
480
-
481
- // export
482
-
483
- export {
484
- // Main functions
485
- createElement,
486
- render,
487
- createRoot,
488
- // Hooks
489
- useStore,
490
- useEffect,
491
- };
1
+ /**
2
+ * The function creates a new element with the given type, props, and children.
3
+ * @param type - The type of the element to be created, such as "div", "span", "h1", etc.
4
+ * @param props - The `props` parameter is an object that contains the properties or attributes of the
5
+ * element being created. These properties can include things like `className`, `id`, `style`, and any
6
+ * other custom attributes that the user wants to add to the element. The `props` object is spread
7
+ * using the spread
8
+ * @param children - The `children` parameter is a rest parameter that allows the function to accept
9
+ * any number of arguments after the `props` parameter. These arguments will be treated as children
10
+ * elements of the created element. The `map` function is used to iterate over each child and create a
11
+ * new element if it is not
12
+ * @returns A JavaScript object with a `type` property and a `props` property. The `type` property is
13
+ * set to the `type` argument passed into the function, and the `props` property is an object that
14
+ * includes any additional properties passed in the `props` argument, as well as a `children` property
15
+ * that is an array of any child elements passed in the `...children` argument
16
+ */
17
+ function createElement(type, props, ...children) {
18
+ return {
19
+ type,
20
+ props: {
21
+ ...props,
22
+ children: children
23
+ .flat()
24
+ .map((child) =>
25
+ typeof child === "object" ? child : createTextElement(child)
26
+ ),
27
+ },
28
+ };
29
+ }
30
+
31
+ /**
32
+ * The function creates a text element with a given text value.
33
+ * @param text - The text content that will be used to create a new text element.
34
+ * @returns A JavaScript object with a `type` property set to `"TEXT_ELEMENT"` and a `props` property
35
+ * that contains a `nodeValue` property set to the `text` parameter and an empty `children` array.
36
+ */
37
+ function createTextElement(text) {
38
+ return {
39
+ type: "TEXT_ELEMENT",
40
+ props: {
41
+ nodeValue: text,
42
+ children: [],
43
+ },
44
+ };
45
+ }
46
+
47
+ /**
48
+ * The function creates a new DOM element based on the given fiber object and updates its properties.
49
+ * @param fiber - The fiber parameter is an object that represents a node in the fiber tree. It
50
+ * contains information about the element type, props, and children of the node.
51
+ * @returns The `createDom` function returns a newly created DOM element based on the `fiber` object
52
+ * passed as an argument. If the `fiber` object represents a text element, a text node is created using
53
+ * `document.createTextNode("")`. Otherwise, a new element is created using
54
+ * `document.createElement(fiber.type)`. The function then calls the `updateDom` function to update the
55
+ * properties of the newly created
56
+ */
57
+ function createDom(fiber) {
58
+ const dom =
59
+ fiber.type == "TEXT_ELEMENT"
60
+ ? document.createTextNode("")
61
+ : document.createElement(fiber.type);
62
+
63
+ updateDom(dom, {}, fiber.props);
64
+
65
+ return dom;
66
+ }
67
+
68
+ const isEvent = (key) => key.startsWith("on");
69
+ const isProperty = (key) => key !== "children" && !isEvent(key);
70
+ const isNew = (prev, next) => (key) => prev[key] !== next[key];
71
+ const isGone = (prev, next) => (key) => !(key in next);
72
+
73
+ /**
74
+ * The function updates the DOM by removing old event listeners and properties, and adding new ones
75
+ * based on the previous and next props.
76
+ * @param dom - The DOM element that needs to be updated with new props.
77
+ * @param prevProps - An object representing the previous props (properties) of a DOM element.
78
+ * @param nextProps - An object containing the new props that need to be updated in the DOM.
79
+ */
80
+ function updateDom(dom, prevProps, nextProps) {
81
+ Object.keys(prevProps)
82
+ .filter(isEvent)
83
+ .filter((key) => !(key in nextProps) || isNew(prevProps, nextProps)(key))
84
+ .forEach((name) => {
85
+ const eventType = name.toLowerCase().substring(2);
86
+ dom.removeEventListener(eventType, prevProps[name]);
87
+ });
88
+
89
+ Object.keys(prevProps)
90
+ .filter(isProperty)
91
+ .filter(isGone(prevProps, nextProps))
92
+ .forEach((name) => {
93
+ dom[name] = "";
94
+ });
95
+
96
+ Object.keys(nextProps)
97
+ .filter(isProperty)
98
+ .filter(isNew(prevProps, nextProps))
99
+ .forEach((name) => {
100
+ dom[name] = nextProps[name];
101
+ });
102
+
103
+ Object.keys(nextProps)
104
+ .filter(isEvent)
105
+ .filter(isNew(prevProps, nextProps))
106
+ .forEach((name) => {
107
+ const eventType = name.toLowerCase().substring(2);
108
+ dom.addEventListener(eventType, nextProps[name]);
109
+ });
110
+ }
111
+
112
+ /**
113
+ * The function commits changes made to the virtual DOM to the actual DOM.
114
+ */
115
+ function commitRoot() {
116
+ deletions.forEach(commitWork);
117
+ commitWork(wipRoot.child);
118
+ currentRoot = wipRoot;
119
+ wipRoot = null;
120
+ }
121
+
122
+ /**
123
+ * The function cancels all effect hooks in a given fiber.
124
+ * @param fiber - The "fiber" parameter is likely referring to a data structure used in React.js to
125
+ * represent a component and its state. It contains information about the component's props, state, and
126
+ * children, as well as metadata used by React to manage updates and rendering. The function
127
+ * "cancelEffects" is likely intended
128
+ */
129
+ function cancelEffects(fiber) {
130
+ if (fiber.hooks) {
131
+ fiber.hooks
132
+ .filter((hook) => hook.tag === "effect" && hook.cancel)
133
+ .forEach((effectHook) => {
134
+ effectHook.cancel();
135
+ });
136
+ }
137
+ }
138
+
139
+ /**
140
+ * The function runs all effect hooks in a given fiber.
141
+ * @param fiber - The "fiber" parameter is likely referring to a data structure used in the
142
+ * implementation of a fiber-based reconciliation algorithm, such as the one used in React. A fiber
143
+ * represents a unit of work that needs to be performed by the reconciliation algorithm, and it
144
+ * contains information about a component and its children, as
145
+ */
146
+ function runEffects(fiber) {
147
+ if (fiber.hooks) {
148
+ fiber.hooks
149
+ .filter((hook) => hook.tag === "effect" && hook.effect)
150
+ .forEach((effectHook) => {
151
+ effectHook.cancel = effectHook.effect();
152
+ });
153
+ }
154
+ }
155
+
156
+ /**
157
+ * The function commits changes made to the DOM based on the effect tag of the fiber.
158
+ * @param fiber - A fiber is a unit of work in Ryunix's reconciliation process. It represents a
159
+ * component and its state at a particular point in time. The `commitWork` function takes a fiber as a
160
+ * parameter to commit the changes made during the reconciliation process to the actual DOM.
161
+ * @returns The function does not return anything, it performs side effects by manipulating the DOM.
162
+ */
163
+ function commitWork(fiber) {
164
+ if (!fiber) {
165
+ return;
166
+ }
167
+
168
+ let domParentFiber = fiber.parent;
169
+ while (!domParentFiber.dom) {
170
+ domParentFiber = domParentFiber.parent;
171
+ }
172
+ const domParent = domParentFiber.dom;
173
+
174
+ if (fiber.effectTag === "PLACEMENT") {
175
+ if (fiber.dom != null) {
176
+ domParent.appendChild(fiber.dom);
177
+ }
178
+ runEffects(fiber);
179
+ } else if (fiber.effectTag === "UPDATE") {
180
+ cancelEffects(fiber);
181
+ if (fiber.dom != null) {
182
+ updateDom(fiber.dom, fiber.alternate.props, fiber.props);
183
+ }
184
+ runEffects(fiber);
185
+ } else if (fiber.effectTag === "DELETION") {
186
+ cancelEffects(fiber);
187
+ commitDeletion(fiber, domParent);
188
+ return;
189
+ }
190
+
191
+ commitWork(fiber.child);
192
+ commitWork(fiber.sibling);
193
+ }
194
+
195
+ /**
196
+ * The function removes a fiber's corresponding DOM node from its parent node or recursively removes
197
+ * its child's DOM node until it finds a node to remove.
198
+ * @param fiber - a fiber node in a fiber tree, which represents a component or an element in the Ryunix
199
+ * application.
200
+ * @param domParent - The parent DOM element from which the fiber's DOM element needs to be removed.
201
+ */
202
+ function commitDeletion(fiber, domParent) {
203
+ if (fiber.dom) {
204
+ domParent.removeChild(fiber.dom);
205
+ } else {
206
+ commitDeletion(fiber.child, domParent);
207
+ }
208
+ }
209
+
210
+ let containerRoot = null;
211
+
212
+ /**
213
+ * The function creates a root container for a web application.
214
+ * @param root - The parameter `root` is likely referring to an HTML element that will serve as the
215
+ * root or container for a web application or component. The `createRoot` function takes this element
216
+ * as an argument and assigns it to a variable called `containerRoot`. This variable can then be used
217
+ * to manipulate the contents
218
+ */
219
+ function createRoot(root) {
220
+ containerRoot = root;
221
+ }
222
+
223
+ /**
224
+ * The function renders an element into a container using a work-in-progress root.
225
+ * @param element - The element parameter is the component or element that needs to be rendered in the
226
+ * container. It could be a Ryunix component or a DOM element.
227
+ * @param container - The container parameter is the DOM element where the rendered element will be
228
+ * appended to. this parameter is optional if you use createRoot().
229
+ */
230
+ function render(element, container) {
231
+ wipRoot = {
232
+ dom: containerRoot || container,
233
+ props: {
234
+ children: [element],
235
+ },
236
+ alternate: currentRoot,
237
+ };
238
+ deletions = [];
239
+ nextUnitOfWork = wipRoot;
240
+ }
241
+
242
+ let nextUnitOfWork = null;
243
+ let currentRoot = null;
244
+ let wipRoot = null;
245
+ let deletions = null;
246
+
247
+ /**
248
+ * This function uses requestIdleCallback to perform work on a fiber tree until it is complete or the
249
+ * browser needs to yield to other tasks.
250
+ * @param deadline - The `deadline` parameter is an object that represents the amount of time the
251
+ * browser has to perform work before it needs to handle other tasks. It has a `timeRemaining()` method
252
+ * that returns the amount of time remaining before the deadline is reached. The `shouldYield` variable
253
+ * is used to determine
254
+ */
255
+ function workLoop(deadline) {
256
+ let shouldYield = false;
257
+ while (nextUnitOfWork && !shouldYield) {
258
+ nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
259
+ shouldYield = deadline.timeRemaining() < 1;
260
+ }
261
+
262
+ if (!nextUnitOfWork && wipRoot) {
263
+ commitRoot();
264
+ }
265
+
266
+ requestIdleCallback(workLoop);
267
+ }
268
+
269
+ requestIdleCallback(workLoop);
270
+
271
+ /**
272
+ * The function performs a unit of work by updating either a function component or a host component and
273
+ * returns the next fiber to be processed.
274
+ * @param fiber - A fiber is a unit of work in Ryunix that represents a component and its state. It
275
+ * contains information about the component's type, props, and children, as well as pointers to its
276
+ * parent, child, and sibling fibers. The `performUnitOfWork` function takes a fiber as a parameter and
277
+ * performs work
278
+ * @returns The function `performUnitOfWork` returns the next fiber to be processed. If the current
279
+ * fiber has a child, it returns the child. Otherwise, it looks for the next sibling of the current
280
+ * fiber. If there are no more siblings, it goes up the tree to the parent and looks for the next
281
+ * sibling of the parent. The function returns `null` if there are no more fibers to process.
282
+ */
283
+ function performUnitOfWork(fiber) {
284
+ const isFunctionComponent = fiber.type instanceof Function;
285
+ if (isFunctionComponent) {
286
+ updateFunctionComponent(fiber);
287
+ } else {
288
+ updateHostComponent(fiber);
289
+ }
290
+ if (fiber.child) {
291
+ return fiber.child;
292
+ }
293
+ let nextFiber = fiber;
294
+ while (nextFiber) {
295
+ if (nextFiber.sibling) {
296
+ return nextFiber.sibling;
297
+ }
298
+ nextFiber = nextFiber.parent;
299
+ }
300
+ }
301
+
302
+ let wipFiber = null;
303
+ let hookIndex = null;
304
+
305
+ /**
306
+ * This function updates a function component by setting up a work-in-progress fiber, resetting the
307
+ * hook index, creating an empty hooks array, rendering the component, and reconciling its children.
308
+ * @param fiber - The fiber parameter is an object that represents a node in the fiber tree. It
309
+ * contains information about the component, its props, state, and children. In this function, it is
310
+ * used to update the state of the component and its children.
311
+ */
312
+ function updateFunctionComponent(fiber) {
313
+ wipFiber = fiber;
314
+ hookIndex = 0;
315
+ wipFiber.hooks = [];
316
+ const children = [fiber.type(fiber.props)];
317
+ reconcileChildren(fiber, children);
318
+ }
319
+
320
+ /**
321
+ * This function updates a host component's DOM element and reconciles its children.
322
+ * @param fiber - A fiber is a unit of work in Ryunix that represents a component and its state. It
323
+ * contains information about the component's type, props, and children, as well as pointers to other
324
+ * fibers in the tree.
325
+ */
326
+ function updateHostComponent(fiber) {
327
+ if (!fiber.dom) {
328
+ fiber.dom = createDom(fiber);
329
+ }
330
+ reconcileChildren(fiber, fiber.props.children.flat());
331
+ }
332
+
333
+ /**
334
+ * This function reconciles the children of a fiber node with a new set of elements, creating new
335
+ * fibers for new elements, updating existing fibers for elements with the same type, and marking old
336
+ * fibers for deletion if they are not present in the new set of elements.
337
+ * @param wipFiber - A work-in-progress fiber object representing a component or element in the virtual
338
+ * DOM tree.
339
+ * @param elements - an array of elements representing the new children to be rendered in the current
340
+ * fiber's subtree
341
+ */
342
+ function reconcileChildren(wipFiber, elements) {
343
+ let index = 0;
344
+ let oldFiber = wipFiber.alternate && wipFiber.alternate.child;
345
+ let prevSibling = null;
346
+
347
+ while (index < elements.length || oldFiber != null) {
348
+ const element = elements[index];
349
+ let newFiber = null;
350
+
351
+ const sameType = oldFiber && element && element.type == oldFiber.type;
352
+
353
+ if (sameType) {
354
+ newFiber = {
355
+ type: oldFiber.type,
356
+ props: element.props,
357
+ dom: oldFiber.dom,
358
+ parent: wipFiber,
359
+ alternate: oldFiber,
360
+ effectTag: "UPDATE",
361
+ };
362
+ }
363
+ if (element && !sameType) {
364
+ newFiber = {
365
+ type: element.type,
366
+ props: element.props,
367
+ dom: null,
368
+ parent: wipFiber,
369
+ alternate: null,
370
+ effectTag: "PLACEMENT",
371
+ };
372
+ }
373
+ if (oldFiber && !sameType) {
374
+ oldFiber.effectTag = "DELETION";
375
+ deletions.push(oldFiber);
376
+ }
377
+
378
+ if (oldFiber) {
379
+ oldFiber = oldFiber.sibling;
380
+ }
381
+
382
+ if (index === 0) {
383
+ wipFiber.child = newFiber;
384
+ } else if (element) {
385
+ prevSibling.sibling = newFiber;
386
+ }
387
+
388
+ prevSibling = newFiber;
389
+ index++;
390
+ }
391
+ }
392
+
393
+ // Hooks
394
+
395
+ /**
396
+ * The function creates a state hook for a Ryunix-like framework.
397
+ * @param initial - The initial value of the state for the hook.
398
+ * @returns The `useStore` function returns an array with two elements: the current state value and a
399
+ * `setState` function that can be used to update the state.
400
+ */
401
+ function useStore(initial) {
402
+ const oldHook =
403
+ wipFiber.alternate &&
404
+ wipFiber.alternate.hooks &&
405
+ wipFiber.alternate.hooks[hookIndex];
406
+ const hook = {
407
+ state: oldHook ? oldHook.state : initial,
408
+ queue: [],
409
+ };
410
+
411
+ const actions = oldHook ? oldHook.queue : [];
412
+ actions.forEach((action) => {
413
+ hook.state = typeof action === "function" ? action(hook.state) : action;
414
+ });
415
+
416
+ /**
417
+ * The function `setState` updates the state of a component in Ryunix by adding an action to a queue
418
+ * and setting up a new work-in-progress root.
419
+ * @param action - The `action` parameter is an object that represents a state update to be performed
420
+ * on a component. It contains information about the type of update to be performed and any new data
421
+ * that needs to be applied to the component's state.
422
+ */
423
+ const setState = (action) => {
424
+ hook.queue.push(action);
425
+ wipRoot = {
426
+ dom: currentRoot.dom,
427
+ props: currentRoot.props,
428
+ alternate: currentRoot,
429
+ };
430
+ nextUnitOfWork = wipRoot;
431
+ deletions = [];
432
+ };
433
+
434
+ wipFiber.hooks.push(hook);
435
+ hookIndex++;
436
+ return [hook.state, setState];
437
+ }
438
+
439
+ /**
440
+ * The function checks if the previous dependencies are different from the next dependencies.
441
+ * @param prevDeps - The previous dependencies, which could be an array of values or objects that a
442
+ * function or component depends on.
443
+ * @param nextDeps - `nextDeps` is an array of dependencies that are being checked for changes. These
444
+ * dependencies are typically used in React's `useEffect` and `useCallback` hooks to determine when a
445
+ * component should re-render or when a function should be re-created.
446
+ */
447
+ const hasDepsChanged = (prevDeps, nextDeps) =>
448
+ !prevDeps ||
449
+ !nextDeps ||
450
+ prevDeps.length !== nextDeps.length ||
451
+ prevDeps.some((dep, index) => dep !== nextDeps[index]);
452
+
453
+ /**
454
+ * This is a function that creates a hook for managing side effects in React components.
455
+ * @param effect - The effect function that will be executed after the component has rendered or when
456
+ * the dependencies have changed. It can perform side effects such as fetching data, updating the DOM,
457
+ * or subscribing to events.
458
+ * @param deps - An array of dependencies that the effect depends on. If any of the dependencies change
459
+ * between renders, the effect will be re-run. If the array is empty, the effect will only run once on
460
+ * mount and never again.
461
+ */
462
+ function useEffect(effect, deps) {
463
+ const oldHook =
464
+ wipFiber.alternate &&
465
+ wipFiber.alternate.hooks &&
466
+ wipFiber.alternate.hooks[hookIndex];
467
+
468
+ const hasChanged = hasDepsChanged(oldHook ? oldHook.deps : undefined, deps);
469
+
470
+ const hook = {
471
+ tag: "effect",
472
+ effect: hasChanged ? effect : null,
473
+ cancel: hasChanged && oldHook && oldHook.cancel,
474
+ deps,
475
+ };
476
+
477
+ wipFiber.hooks.push(hook);
478
+ hookIndex++;
479
+ }
480
+
481
+ // export
482
+
483
+ export {
484
+ // Main functions
485
+ createElement,
486
+ render,
487
+ createRoot,
488
+ // Hooks
489
+ useStore,
490
+ useEffect,
491
+ };
package/lib/main.js CHANGED
@@ -1,13 +1,10 @@
1
- import { createElement, render, createRoot } from "./dom";
2
- import { useStore, useEffect } from "./dom";
3
-
4
- // Hooks
5
- export { useStore, useEffect };
6
-
7
- // General
8
-
9
- export default {
10
- createElement,
11
- render,
12
- createRoot,
13
- };
1
+ import { createElement, render, createRoot } from "./dom";
2
+ import { useStore, useEffect } from "./dom";
3
+
4
+ export { useStore, useEffect, createElement, render, createRoot };
5
+
6
+ export default {
7
+ createElement,
8
+ render,
9
+ createRoot,
10
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unsetsoft/ryunixjs",
3
- "version": "0.2.6-alpha.8",
3
+ "version": "0.2.6",
4
4
  "license": "MIT",
5
5
  "main": "./dist/Ryunix.js",
6
6
  "private": false,
@@ -16,23 +16,26 @@
16
16
  "ryunix": "./bin/index.js"
17
17
  },
18
18
  "dependencies": {
19
+ "terminal-log": "^1.0.1",
20
+ "sass": "^1.66.1",
21
+ "url-loader": "^4.1.1",
19
22
  "rollup": "3.24.0",
20
23
  "yargs": "^17.7.2",
21
- "webpack": "^5.86.0",
22
- "@babel/core": "^7.22.5",
24
+ "@babel/core": "^7.22.11",
23
25
  "@babel/plugin-proposal-class-properties": "^7.18.6",
24
26
  "@babel/plugin-transform-react-jsx": "^7.22.5",
25
- "@babel/preset-env": "^7.22.5",
27
+ "@babel/preset-env": "^7.22.14",
26
28
  "@babel/preset-react": "^7.22.5",
27
- "babel-loader": "^9.1.2",
28
- "css-loader": "6.8.1",
29
+ "babel-loader": "^9.1.3",
30
+ "css-loader": "^6.8.1",
29
31
  "error-overlay-webpack-plugin": "^1.1.1",
30
32
  "file-loader": "^6.2.0",
31
- "html-webpack-plugin": "^5.5.2",
33
+ "html-webpack-plugin": "^5.5.3",
32
34
  "image-webpack-loader": "8.1.0",
33
35
  "node-sass": "9.0.0",
34
- "sass-loader": "13.3.2",
35
- "style-loader": "3.3.3",
36
+ "sass-loader": "^13.3.2",
37
+ "style-loader": "^3.3.3",
38
+ "webpack": "^5.88.2",
36
39
  "webpack-cli": "^5.1.4",
37
40
  "webpack-dev-server": "^4.15.1"
38
41
  },
package/webpack.config.js CHANGED
@@ -1,47 +1,54 @@
1
- const path = require("path");
2
- const HtmlWebpackPlugin = require("html-webpack-plugin");
3
- const ErrorOverlayPlugin = require("error-overlay-webpack-plugin");
4
-
5
- const dir = path.dirname(require.main.filename);
6
- console.log(dir);
7
- module.exports = {
8
- mode: process.env.NODE_ENV !== "production" ? "development" : "production",
9
- entry: path.resolve(dir, "src", "main.ryx"),
10
- output: {
11
- path: path.resolve(dir, ".ryunix"),
12
- filename: "./assets/js/[chunkhash].bundle.js",
13
- },
14
-
15
- module: {
16
- rules: [
17
- {
18
- test: /\.(js|jsx|ts|tsx|ryx)$/,
19
- exclude: /node_modules/,
20
- use: {
21
- loader: "babel-loader",
22
- options: {
23
- presets: ["@babel/preset-env", "@babel/preset-react"],
24
- },
25
- },
26
- },
27
- {
28
- test: /\.(css|scss)$/,
29
- use: ["style-loader", "css-loader"],
30
- },
31
- {
32
- test: /\.(jpg|jpeg|png|gif|mp3|svg|mp4)$/,
33
- use: ["file-loader"],
34
- },
35
- ],
36
- },
37
- resolve: {
38
- extensions: ["*", ".js", ".jsx", ".ts", ".tsx", ".ryx"],
39
- },
40
- plugins: [
41
- new HtmlWebpackPlugin({
42
- template: path.join(dir, "public", "index.html"),
43
- //favicon: path.join(dir, "public", "favicon.ico"),
44
- }),
45
- new ErrorOverlayPlugin(),
46
- ],
47
- };
1
+ const path = require("path");
2
+ const HtmlWebpackPlugin = require("html-webpack-plugin");
3
+ const ErrorOverlayPlugin = require("error-overlay-webpack-plugin");
4
+
5
+ const dir = path.dirname(path.resolve(path.join(__dirname, "/../", "../")));
6
+ console.log(path.join(dir, "src", "main.ryx"), __dirname);
7
+
8
+ module.exports = {
9
+ mode: "production",
10
+ entry: path.join(dir, "src", "main.ryx"),
11
+ output: {
12
+ path: path.join(dir, ".ryunix"),
13
+
14
+ filename: "./assets/js/[chunkhash].bundle.js",
15
+ devtoolModuleFilenameTemplate: "ryunix/[resource-path]",
16
+ },
17
+
18
+ module: {
19
+ rules: [
20
+ {
21
+ test: /\.(js|jsx|ts|tsx|ryx)$/,
22
+ exclude: /node_modules/,
23
+ use: {
24
+ loader: "babel-loader",
25
+ options: {
26
+ presets: ["@babel/preset-env", "@babel/preset-react"],
27
+ },
28
+ },
29
+ },
30
+ {
31
+ test: /\.(sa|sc|c)ss$/,
32
+ use: ["style-loader", "css-loader", "sass-loader"],
33
+ },
34
+ {
35
+ test: /\.(jpg|jpeg|png|gif|mp3|svg|mp4)$/,
36
+ use: ["file-loader"],
37
+ },
38
+ {
39
+ test: /\.(png|woff|woff2|eot|ttf|svg)$/, // to import images and fonts
40
+ loader: "url-loader",
41
+ options: { limit: false },
42
+ },
43
+ ],
44
+ },
45
+ resolve: {
46
+ extensions: ["*", ".js", ".jsx", ".ts", ".tsx", ".ryx"],
47
+ },
48
+ plugins: [
49
+ new HtmlWebpackPlugin({
50
+ template: path.join(dir, "public", "index.html"),
51
+ }),
52
+ new ErrorOverlayPlugin(),
53
+ ],
54
+ };
package/.babelrc DELETED
@@ -1,20 +0,0 @@
1
- {
2
- "presets": [
3
- "@babel/preset-env",
4
- [
5
- "@babel/preset-react",
6
- {
7
- "runtime": "automatic"
8
- }
9
- ]
10
- ],
11
- "plugins": [
12
- [
13
- "@babel/plugin-transform-react-jsx",
14
- {
15
- "pragma": "Ryunix.createElement"
16
- }
17
- ],
18
- "@babel/plugin-proposal-class-properties"
19
- ]
20
- }