Skip to content
This repository was archived by the owner on May 19, 2023. It is now read-only.

Commit fff6e43

Browse files
committed
docs: create guidelines
1 parent e7d0904 commit fff6e43

File tree

5 files changed

+281
-0
lines changed

5 files changed

+281
-0
lines changed

.github/CODE_OF_CONDUCT.md

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Contributor Covenant Code of Conduct
2+
3+
## Our Pledge
4+
5+
In the interest of fostering an open and welcoming environment, we as
6+
contributors and maintainers pledge to making participation in our project and
7+
our community a harassment-free experience for everyone, regardless of age, body
8+
size, disability, ethnicity, sex characteristics, gender identity and expression,
9+
level of experience, education, socio-economic status, nationality, personal
10+
appearance, race, religion, or sexual identity and orientation.
11+
12+
## Our Standards
13+
14+
Examples of behavior that contributes to creating a positive environment
15+
include:
16+
17+
- Using welcoming and inclusive language
18+
- Being respectful of differing viewpoints and experiences
19+
- Gracefully accepting constructive criticism
20+
- Focusing on what is best for the community
21+
- Showing empathy towards other community members
22+
23+
Examples of unacceptable behavior by participants include:
24+
25+
- The use of sexualized language or imagery and unwelcome sexual attention or
26+
advances
27+
- Trolling, insulting/derogatory comments, and personal or political attacks
28+
- Public or private harassment
29+
- Publishing others' private information, such as a physical or electronic
30+
address, without explicit permission
31+
- Other conduct which could reasonably be considered inappropriate in a
32+
professional setting
33+
34+
## Our Responsibilities
35+
36+
Project maintainers are responsible for clarifying the standards of acceptable
37+
behavior and are expected to take appropriate and fair corrective action in
38+
response to any instances of unacceptable behavior.
39+
40+
Project maintainers have the right and responsibility to remove, edit, or
41+
reject comments, commits, code, wiki edits, issues, and other contributions
42+
that are not aligned to this Code of Conduct, or to ban temporarily or
43+
permanently any contributor for other behaviors that they deem inappropriate,
44+
threatening, offensive, or harmful.
45+
46+
## Scope
47+
48+
This Code of Conduct applies both within project spaces and in public spaces
49+
when an individual is representing the project or its community. Examples of
50+
representing a project or community include using an official project e-mail
51+
address, posting via an official social media account, or acting as an appointed
52+
representative at an online or offline event. Representation of a project may be
53+
further defined and clarified by project maintainers.
54+
55+
## Enforcement
56+
57+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
58+
reported by contacting the project team at hello@aidenybai.com. All
59+
complaints will be reviewed and investigated and will result in a response that
60+
is deemed necessary and appropriate to the circumstances. The project team is
61+
obligated to maintain confidentiality with regard to the reporter of an incident.
62+
Further details of specific enforcement policies may be posted separately.
63+
64+
Project maintainers who do not follow or enforce the Code of Conduct in good
65+
faith may face temporary or permanent repercussions as determined by other
66+
members of the project's leadership.
67+
68+
## Attribution
69+
70+
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 1.4,
71+
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72+
73+
For answers to common questions about this code of conduct, see
74+
https://www.contributor-covenant.org/faq

.github/COMMIT_CONVENTION.md

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
## Git Commit Message Convention
2+
3+
> This is adapted from [Angular's commit convention](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular).
4+
5+
#### TL;DR:
6+
7+
Messages must be matched by the following regex:
8+
9+
```js
10+
/^(revert: )?(feat|fix|docs|style|refactor|perf|test|workflow|build|ci|chore|types|wip)(\(.+\))?: .{1,72}/;
11+
```
12+
13+
### Full Message Format
14+
15+
A commit message consists of a **header**, **body** and **footer**. The header has a **type**, **scope** and **subject**:
16+
17+
```
18+
<type>(<scope>): <subject>
19+
<BLANK LINE>
20+
<body>
21+
<BLANK LINE>
22+
<footer>
23+
```
24+
25+
The **header** is mandatory and the **scope** of the header is optional.
26+
27+
### Revert
28+
29+
If the commit reverts a previous commit, it should begin with `revert:`, followed by the header of the reverted commit. In the body, it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted.
30+
31+
### Type
32+
33+
If the prefix is `feat`, `fix` or `perf`, it will appear in the changelog. However, if there is any [BREAKING CHANGE](#footer), the commit will always appear in the changelog.
34+
35+
Other prefixes are up to your discretion. Suggested prefixes are `docs`, `chore`, `style`, `refactor`, and `test` for non-changelog related tasks.
36+
37+
### Scope
38+
39+
The scope could be anything specifying the place of the commit change.
40+
41+
### Subject
42+
43+
The subject contains a succinct description of the change:
44+
45+
- use the imperative, present tense: "change" not "changed" nor "changes"
46+
- don't capitalize the first letter
47+
- no dot (.) at the end
48+
49+
### Body
50+
51+
Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes".
52+
The body should include the motivation for the change and contrast this with previous behavior.
53+
54+
### Footer
55+
56+
The footer should contain any information about **Breaking Changes** and is also the place to
57+
reference GitHub issues that this commit **Closes**.
58+
59+
**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.

.github/CONTRIBUTING.md

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Contributing to Lucia
2+
3+
### Initial Steps:
4+
5+
1. Fork this repository and clone it to your local machine
6+
2. Make sure you have `yarn` installed. If you don't, run `npm install -g yarn`
7+
3. Install all packages with the `yarn` command in the project root.
8+
9+
Once you are setup, you check out the codebase documentation to learn more!
10+
- [`WORKFLOW.md`](../codebase/WORKFLOW.md) - How to get started with iterating, building, and ad-hoc testing Lucia.
11+
- [`CORE.md`](../codebase/CORE.md) - Understanding the internals and how the core is structured.
12+
13+
## Next Steps + Useful Info:
14+
15+
- We are using Yarn as our package manager, please do not commit your `package-lock.json` files from NPM
16+
- Make sure you are up to date by doing `git pull` here and there.
17+
- Submit a [pull request](https://github.com/aidenybai/lucia/pulls)!

docs/CORE.md

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Core Documentation
2+
3+
This document covers how Lucia's core works. It's intended to aid in understanding the code, and helping contributors work with it.
4+
5+
Note that there are some design decisions that make Lucia's core somewhat unorthodox. Keep in mind that this project is quite young and unstable, and some of the implementations are bound to change down the road.
6+
7+
The Lucia's core isn't used to be rendered, mutated, and synced with the DOM, rather it is used as a reference of dynamic nodes during rendering. This mean in the core, no explicit diffing occurs and values that are compiled are readonly.
8+
9+
The reasoning behind this architectural decision isn't necessarily because it is more efficient, rather it's just not necessary in Lucia's use case.
10+
11+
## Design Principles
12+
13+
The Lucia' core is designed to accomplish a balance between being **fast and compact**, by trying to execute as **few DOM operations** as it can. It achieves this by relying on directives created by the user.
14+
15+
- **Avoid doing unnecessary work**
16+
17+
Lucia only compiles the AST with only dynamic nodes, with static nodes being garbage collected. Lucia also optimizes the AST by making directives, dependencies, and the state's size immutable. This allows for straightforward dependency tracking and thereby making the least amount of DOM operations possible.
18+
19+
- **Balance mutability while enforcing simple patterns**
20+
21+
Many patterns in other libraries, such as the mutability of the view are often expensive on performance. Lucia attempts to resolve this through immutable directives (and thereby dependencies), allowing flexibility for the user while maintaining good performance. This way the runtime renderer does not need to check depedencies, interpretation, etc. every render cycle.
22+
23+
- **Keep the core as lightweight as possible**
24+
25+
The goal of Lucia is to be as light as possible, meaning that to achieve this, less code needs to be written. The core should be as fundemental and simple as possible, with abstractions filling in the additional functionality.
26+
27+
## Overview
28+
29+
<p align="center"><img src="https://raw.githubusercontent.com/aidenybai/lucia/master/.github/img/flowchart.svg" alt="Diagram of build pipeline" width="752"></p>
30+
31+
Lucia's Core is composed of two phases: compilation and runtime.
32+
33+
### Compiler
34+
35+
The compiler's purpose is to generate an AST for the renderer to reference. It first fetches all of the nodes under the specified node, inclusive of its root, then flattening it into an array. After that, it systematically picks out dynamic nodes through two conditions:
36+
37+
1. Has directives `(STATIC)`
38+
2. Has dependencies in directives `(DYNAMIC)`
39+
3. Static node `(NULL)`
40+
41+
Passing these two conditions will result in the creation of the AST.
42+
43+
**Abstract Syntax Tree**
44+
45+
The AST is an array of ASTNodes. An ASTNode looks like this:
46+
47+
```ts
48+
interface ASTNode {
49+
directives: {...};
50+
deps: string[];
51+
el: HTMLElement;
52+
type: -1 | 0 | 1;
53+
}
54+
```
55+
56+
The `directives` property is used to data that includes reusuable functions of the directives on the specific element. We will talk more about this later. The `deps` property contains an array of dependency keys of all the directives of the element. The `el` property contains the element for the renderer to use. The `type` property can only be `0 (STATIC)` or `1 (DYNAMIC)`. This is important as the renderer garbage collects static nodes, which do not contain any dependencies.
57+
58+
**Directives and DirectiveData**
59+
60+
The values of the `directives` object are `DirectiveData`, which contain properties that the renderer can use. This is what it looks like:
61+
62+
```ts
63+
interface DirectiveData {
64+
compute: (state: KV<unknown>, event?: Event) => any;
65+
value: string;
66+
deps: string[];
67+
}
68+
```
69+
70+
The `compute` function interprets and evaluates the `value`, passing the state from `compute`'s state parameter. Notice how there is a duplicate `deps` property for the `DirectiveData`. This functionally is the same as the ASTNode `deps`, but is for more fine tuned for dependency tracking. This pertains only to its own directive, while the ASTNode `deps` pertains to all of the directives.
71+
72+
**Performance Decisions**
73+
74+
The compiler intentionally handles a lot of the decision-making, such as dependency-tracking and only using dynamic nodes. These actions allow for better performace at runtime, but requires immutability. This makes Lucia less flexible, but it is possible to achieve the same goal with different patterns.
75+
76+
### Renderer
77+
78+
The renderer's purpose is to change the DOM based on the state. It does this by iterating over the AST from the compiler, checking dependencies against changed dependencies supplied by the observer, and rendering directives if necessary.
79+
80+
**Garbage Collection**
81+
82+
There are two types of ASTNodes as designated by the compiler: `0 (STATIC)` and `1 (DYNAMIC)`. Static ASTNodes refer to ASTNodes with directives, but no dependencies. Since directives are immutable, these nodes only need to be rendered once. After they are rendered, they are pushed to a queue. After all affected ASTNodes are rendered, they are deleted from the AST. This means that unnecessary iteration is removed, boosting performance.
83+
84+
**Expression Computation and Interpretation**
85+
86+
Since directives are special attributes, the value of directives are strings. Lucia first attempts to determine the exact dependency, so it can just access by state property. It currently supports direct key (`prop`), bypassing the need to evalute the expression. If it is not able to interpret the properties from the directive value, it will use the [`new Function()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function) syntax to execute.
87+
88+
### Observer
89+
90+
The observer's purpose is to detect changes in the state and run a callback render function on change. This is useful because we only want to render if the state changes, as the content of the DOM is directly connected to the state.
91+
92+
To do this, a JavaScript object is provided, [sealed](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/seal), and wrapped with a [Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy). This allows the `get` and `set` traps to be set. The observer automatically attempts to proxify nested arrays and objects, so that callback renders are able to be handled on change.
93+
94+
**Special Cases**
95+
96+
Some cases, such as array mutations using methods, such as `push` and `pop`, Proxy's are updated two times. The first change is a change in value, then in length. This can vary in order or in presense based on the type of mutation, meaning that both traps need to be accountd for. This means it renders both times, which is a minor performance bottleneck.
97+
98+
Another peculiarity of Proxy's is that changed information (`target`, `key`, `value`) are based on the current object, not the root object. This means that if there is a nested object in the state, the target will not be the root node, messing up our dependencies. What the observer currently does is go to root and attempt to find the affected object that contains the dependencies.
99+
100+
Lastly, methods are immutable. This is because there is dependency-tracking during compilation on the stringified content of methods.

docs/WORKFLOW.md

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
## Workflow Documentation
2+
3+
Lucia is written in [TypeScript](https://www.typescriptlang.org) and should be run in a browser environment. We highly recommend you use [VSCode](https://code.visualstudio.com/) as your IDE when developing.
4+
5+
### Yarn Scripts
6+
7+
- `dev` - This script builds the codebase and watches for changes into a `iife` distribution bundle using [esbuild](http://esbuild.github.io/)
8+
- `build` - This script builds the codebase into a `iife`, `cjs`, and `esm` format distribution bundles using [Rollup](https://rollupjs.org/)
9+
- `lint` - This script uses [ESLint](https://eslint.org/) to lint the codebase
10+
- `lint:fix` - This script uses [ESLint](https://eslint.org/) to lint the codebase and attempts to fix any errors
11+
- `cleanup` - This script uses [Prettier](https://prettier.io/) to format the codebase
12+
- `test` - This script runs unit tests (specified under `__test__` folders) using [Jest](https://jestjs.io/)
13+
- `release` - This script runs the aformentioned scripts and publishes the project on NPM
14+
15+
### Iterating
16+
17+
You can create a `*.html` (e.g. `test.html`) file at root to test changes in realtime. We recommend using [`live-server`](https://www.npmjs.com/package/live-server) to hot-reload the webpage on change, and edit as necessary.
18+
19+
Below is a sample for a Lucia starter:
20+
21+
```html
22+
<!DOCTYPE html>
23+
<html>
24+
<head>
25+
<script src="./dist/lucia.dev.js"></script>
26+
</head>
27+
<body>
28+
<!-- Your code here -->
29+
</body>
30+
</html>
31+
```

0 commit comments

Comments
 (0)