From 8058d047a5a50406ff4175c83b8488eea7c4e706 Mon Sep 17 00:00:00 2001 From: Akshay Nair Date: Fri, 25 Aug 2023 18:58:47 +0530 Subject: docs: crazy amounts of docs --- docs/README.md | 9 ++ docs/api/functions.md | 266 +++++++++++++++++++++++++++++++++++++++++++++----- docs/how-it-works.md | 130 ++++++++++++++++++++++++ docs/how_it_works.md | 4 - docs/recipies.md | 6 ++ 5 files changed, 385 insertions(+), 30 deletions(-) create mode 100644 docs/how-it-works.md delete mode 100644 docs/how_it_works.md (limited to 'docs') diff --git a/docs/README.md b/docs/README.md index e69de29..0e2fb78 100644 --- a/docs/README.md +++ b/docs/README.md @@ -0,0 +1,9 @@ +# Documentation + +- [API/functions](./api/functions.md) +- [API/hooks](./api/hooks.md) +- [API/properties](./api/properties.md) +- [How it works?](./how-it-works.md) +- [Security](./security.md) +- [Common recipies](./recipies.md) + diff --git a/docs/api/functions.md b/docs/api/functions.md index 39f85cb..55fd701 100644 --- a/docs/api/functions.md +++ b/docs/api/functions.md @@ -5,19 +5,33 @@ type custom-property-name = `--${string}` type selector = string // Any css selector or identifier (used as id) type condition = string // empty string, 0, 'false', "'false'" and "\"false\"" are all false, the rest are fine. Don't ask. type duration = number | `${number}ms` | `${number}s` +type pair = string: any ``` -## get-var -Get css custom property from an element +=== + + +## Core + +### get-var +Get css custom property from an element. Basically var but evaluated lazily. NOTE: Avoid using `var` inside cssx expressions. ```typescript function get-var(custom-property-name): string -function get-var(selector, custom-property-name): string +function get-var(custom-property-name, default-value): string +``` + +Example - +```css +#my-element { + --cssx-text: get-var(--some-variable); +} ``` -## update + +#### update Update a css custom property on an element ```typescript @@ -25,24 +39,230 @@ function update(custom-property-name, string): void function update(selector, custom-property-name, string): string ``` +Example - +```css +#my-element { + --cssx-on-click: update(some-el, --text, attr(input-element, 'value')); -## js-eval -Evaluate any js expression. Easy escape hatch into writing the worst code humanly possible. + --cssx-children: input#input-element #some-el; +} -```typescript -function js-eval(string): string +#some-el { --text: "default"; } +#some-el::after { content: var(--text); } ``` -## if +### if If expression. You know how this one goes. If truthy, it'll pick the second argument, else the third. ```typescript function if(condition, any, any): any ``` +Example - +```css +#my-element { + --boolean: false; + + --cssx-on-update: + update(background-color, + if( + get-var(--boolean) + 'DarkGoldenRod', + 'PapayaWhip' + ) + ); +} +``` + +### map +A constructor function to create a map of key value pairs. + +```typescript +function map(...pair): map +``` + +Example - +```css +#my-element { + --cssx-children: instance( + div#some-element, + map(--prop1: "hello", --prop2: "world") + ); +} +``` + +### seq +> WIP Docs + +### call +Call a "function". A function is any series of expressions defined in a css custom property. -## delay +NOTE: Every function call creates a new dom node for computing the result. Dom nodes are the call stack. + +```typescript +function call(var-identifier, map): any +``` + +Example - +```css +#my-element { + --factorial: if( + js-expr(string(get-var(--n), '> 1')), + js-expr(string( + get-var(--n), + ' * ', + call(--factorial, map(--n: js-expr(string(get-var(--n), ' - 1')))) + )), + 1 + ); + + --cssx-on-mount: js-expr(string( + 'console.log("', + call(--factorial, map(--n: 5)), + '")' + )); +} +``` + +Or let's just go nuts with functions. +Because we use named properties as arguments and css is cascading, all named properties are implicitly available to everything getting called. + +> Not a design choice, a design consequence. + +So `--left` and `--right` is implicitly available to `--binary-op`. + +> NOTE: `func` in `--binary-op` doesn't do anything. It's to make the developer feel better. + +```css +#my-element { + --binary-op: + func(--left, --op, --right) + js-expr(string(get-var(--left), get-var(--op), get-var(--right))); + --greater-than: call(--binary-op, map(--op: ' >= ')); + --minus: call(--binary-op, map(--op: ' - ')); + --multiply: call(--binary-op, map(--op: ' * ')); + + --factorial: if(call(--greater-than, map(--left: get-var(--n), --right: 1)), + call(--multiply, map( + --left: get-var(--n), + --right: call(--factorial, + map(--n: call(--minus, + map(--left: get-var(--n), --right: 1))) + ) + )), + 1 + ); +} +``` + +### string +Concatenate strings together / Cast a value to string explicitly + +```typescript +function string(...string): string +``` + +```css +#my-element { + --log-stuff: 'Stuff to log to console'; + --cssx-on-mount: js-expr(string('console.log("', get-var(--log-stuff), '")')); +} +``` + +### quotify +Add quotes around a value + +```typescript +function quotify(string): `'${string}'` +``` + +```css +#my-element { + --log-stuff: 'Stuff to log to console'; + --cssx-on-mount: js-expr(string('console.log(', quotify(get-var(--log-stuff)), ')')); +} +``` + + +### unquotify +Remove quotes from a value. No example here, use your imagination. + +```typescript +function quotify(string): string +``` + + +### do +Evaluate a series of expressions in sequence and return the last value. + +```css +#my-element { + --cssx-on-mount: + if(get-var(--some-boolean), + do( + add-class(loading), + delay(1s), + remove-class(loading) + ), + noop(), + ) + ; +} +``` + + +### try +The standard try/catch as an expression. The error expression is scoped and gets access to a `--error` value. + +```css +form#my-form { + --cssx-on-submit: + prevent-default() + add-class(form, 'submitting') + try( + do( + request('/your-api/some-api', 'POST'), + add-class(form, 'submitted') + ), + js-eval(string('alert("', get-var(--error), '")')) + ) + remove-class(form, 'submitting') + ; +} +``` + +### let +Create a binding for use inside a scoped expression. + +`--random` is only available within the let binding +```css +#my-element { + --cssx-on-mount: + let(--random, js-eval('Math.random()'), + js-eval('alert("', get-var(--random),'")') + ) + ; +} +``` + + +=== + + +## Others + +### js-eval +Evaluate any js expression. Easy escape hatch directly to hell. + +```typescript +function js-eval(string): string +``` + +### request +> WIP Docs + +### delay Wait a bit. ```typescript @@ -56,36 +276,30 @@ Examples for input - - `delay(0.5s)`: wait for 500 milliseconds -## load-cssx - - -## set-attr - - -## attr - +=== -## prevent-default +## DOM -## request +### load-cssx +Load more of this abomination into your page -## add-children +### set-attr -## remove-element +### attr -## call-method +### add-children -## map +### remove-element -## call +### prevent-default -## func +### call-method diff --git a/docs/how-it-works.md b/docs/how-it-works.md new file mode 100644 index 0000000..c4d6fe3 --- /dev/null +++ b/docs/how-it-works.md @@ -0,0 +1,130 @@ +# How does it work? +Who knows really? It's just magic for the most part. + +## Creating the dom tree + +Everything starts with the `body` element (by default). + +In your css, you can use `body` or `html` or `:root`. As long as your root (body by default) inherits that property, it's all good. +```css +:root { + --cssx-children: div#my-element; +} +``` + +This will create a div inside `body` with the `id` (and `data-element` attribute) of `my-element`. + + +Let's go deeper... + +```css +:root { + --cssx-children: div#my-element; +} + +#my-element { + --cssx-children: header#div-a main#div-b; +} +``` + +Now `my-element`, gets 2 children. You can probably figure out what those would look like. + +> NOTE: The styles for `#my-element` has to be loaded into the dom before the + + +You may have already noticed a problem here. If you don't override the --cssx-children property, wouldn't all children of body get access to that? + +Well yeah, which is why, we have a `.cssx-layer` element between the parent and children. This element wraps all children and makes it so all the cssx property are unset. This can occasionally make styling a bit difficult but that's a YOU problem for trying to use this. + + +## Instances +Instances are sort of like components. You can instantiate elements and provide them some custom properties. + +NOTE: Instances get unique ids so instances and children of instances cannot not use the id selector for the definition. + +```css +#my-element { + --cssx-children: + instance(div#user-card, map(--name: "Sugom Afart", --age: 20)) + instance(div#user-card, map(--name: "Leeki Bahol", --age: 69)) + instance(div#user-card, map(--name: "Yamam Aho", --age: 40)) + ; +} + +[data-instance=user-card] { + --name: "default name"; + --age: 0; + + --cssx-children: div#name div#age; +} + +[data-element=name]::after { + /* Using the ::after element to set content via css */ + content: "Name: " var(--name); +} +[data-element=age] { + /* Using the --cssx-text property because css doesn't like numbers in `content` */ + --cssx-text: string("Age: ", get-var(--age)); +} +``` + + + +## Custom functions + +This is by far the most "fun" aspect of this project. Take a look at the docs for [call](./api/functions.md#call) for the api and examples. + +```css +#my-element { + --factorial: + func(--n) + if( + js-expr(string(get-var(--n), '> 1')), + js-expr(string( + get-var(--n), + ' * ', + call(--factorial, map(--n: js-expr(string(get-var(--n), ' - 1')))) + )), + 1 + ); + + --cssx-on-mount: js-expr(string( + 'console.log("', + call(--factorial, map(--n: 5)), + '")' + )); +} +``` + +NOTE: `func` is noop and just exists for documentation. You can also do `func(--a: string, --b: number)` and it'll be valid syntax but ignored at evaluation. So basically, typescript. + +The way this works is that it creates a new dom element inside the caller (`#my-element`), which then becomes the scope for the function. +Whatever arguments are passed to call will be added as css properties to this dom element. +Then the expressions inside the function is evaluated within the context of that element. + +This means that with `call(--factorial, map(--n: 5))` the dom tree would look something like this. + +```html +
+
+ +
+
+
+
+
+
+
+
+
+
+
+``` + +This is the call stack. This is immedietely deleted as soon as the required computation is completed. + +> PRO TIP 1: If you want the tree to persist even after the function is evaluated for debugging, add the `data-debug-stack` attribute to the caller element +> PRO TIP 2: You could style these nodes to have this tree show up in the ui and use the `--cssx-text` property to display the arguments for each recursive function call +> PRO TIP 3: If you're running into infinite loops, good luck. Also, you can add `delay(1s)` at the start to slow things down to debug. + + diff --git a/docs/how_it_works.md b/docs/how_it_works.md deleted file mode 100644 index 6329723..0000000 --- a/docs/how_it_works.md +++ /dev/null @@ -1,4 +0,0 @@ -# How does it work? - -WIP - diff --git a/docs/recipies.md b/docs/recipies.md index 52dddf4..133f69f 100644 --- a/docs/recipies.md +++ b/docs/recipies.md @@ -95,3 +95,9 @@ NOTE: Try to avoid doing this. Please refer to [./security.md](./security.md) fo } ``` + +## Debugging call stack + +> WIP docs + + -- cgit v1.3.1