[WIP] Rename and continue tweaking things

This commit is contained in:
Talia 2025-02-20 23:40:09 +01:00
parent 0fd7fcb399
commit 781f870890
Signed by: darkwiiplayer
GPG key ID: 7808674088232B3E
3 changed files with 89 additions and 100 deletions

View file

@ -4,13 +4,21 @@
<script type="module" src="https://cdn.jsdelivr.net/gh/darkwiiplayer/components@master/TypeWriter.js"></script>
<script type="importmap">
{
"imports": {
"nyooom/render": "https://cdn.jsdelivr.net/gh/darkwiiplayer/nyooom@d457c38/render.js",
"nyooom/observable": "https://cdn.jsdelivr.net/gh/darkwiiplayer/nyooom@d457c38/observable.js",
"nyooom/showcase": "./js/nyooom-showcase.js"
}
}
</script>
<style>
@import
/* url('https://cdn.jsdelivr.net/gh/darkwiiplayer/css@main/all.css') */
url('https://darkwiiplayer.github.io/css/all.css') layer(framework);
@import
/* url('https://cdn.jsdelivr.net/gh/darkwiiplayer/css@main/schemes/talia.css') */
url('https://darkwiiplayer.github.io/css/schemes/talia.css') layer(theme);
@import url('styles.css') layer(site);
.jsdelivr-badge {
@ -45,7 +53,7 @@
</script>
<script type="module">
import "./js/SkoomaShowcase.js"
import "nyooom/showcase"
</script>
<a name=top></a>
@ -54,19 +62,19 @@
<nav class="bar">
<ul>
<li><a href="#top">Top</a></li>
<li><a href="#getting-started">Getting Started</a></li>
<li><a href="https://github.com/darkwiiplayer/skooma-js">GitHub</a></li>
<li><a href="https://www.npmjs.com/package/skooma">npm</a></li>
<li><a href="https://git.but.gay/darkwiiplayer/nyooom">Git</a></li>
<li><a href="https://github.com/darkwiiplayer/nyooom">Github</a></li>
<li><a href="https://www.npmjs.com/package/nyooom">npm</a></li>
</ul>
</nav>
<img alt="" class="jsdelivr-badge" src="https://data.jsdelivr.com/v1/package/npm/skooma/badge">
<img alt="" class="jsdelivr-badge" src="https://data.jsdelivr.com/v1/package/npm/nyooom/badge">
</header>
<page-hero role="banner" cover=60>
<!-- <img src="https://picsum.photos/1920/1080"> -->
<hgroup>
<h1 style="font-size: 6vw">Skooma</span></h1>
<code lang="js">import { html } from "skooma/render.js"</code>
<h1 style="font-size: 6vw">Nyooom</span></h1>
<code lang="js">import { html } from "nyooom/render"</code>
<p>
A new way of building
<type-writer loop>
@ -91,23 +99,23 @@
<h2>Elevator Pitch</h2>
<p class="big">
Skooma combines <em>easy</em> and <em>powerful</em> HTML generation with optional <em>reactivity</em>, all in plain JavaScript.
Nyooom combines <em>easy</em> and <em>powerful</em> HTML generation with optional <em>reactivity</em>, all in plain JavaScript.
</p>
<skooma-showcase>
<nyooom-showcase preview=false>
<code><div contenteditable="false">return html.p(
"Text Node",
html.br(),
html.b("HTML Node"),
{style:{color:"salmon"}},
)</div></code>
</skooma-showcase>
</nyooom-showcase>
<vertical-spacer></vertical-spacer>
<p>
Skooma is <em>small</em> enough that you can use it even if you only need it in a single function,
<em>easy</em> enough to figure out what's going on even if you've never used it,
Nyooom is <em>small</em> enough that you can use it even if you only need it in a single function,
<em>obvious</em> enough to figure out what's going on even if you've never used it,
<em>powerful</em> enough that you won't <i>need</i> another framework and
<em>flexible</em> enough to let you use one regardless.
</p>
@ -115,10 +123,6 @@
<p>
If that sounds good, it's time to back up those claims!
</p>
<p>
Continue reading to get an overview of how skooma works and what it can do.<br>
Or jump down to the <a href="#skooma-explained">explainer</a> to get a more detailed explanation of what skooma is good at and why.
</p>
</div>
</section>
@ -126,33 +130,32 @@
<h2>Getting Started</h2>
<section>
<p class="big">
Trying out skooma is super easy!<br>
Just import the <code>html</code> export into your script and start generating DOM nodes.
<p>
Trying out nyooom is super easy:
</p>
<pre><code lang=js>import {html} from "https://cdn.jsdelivr.net/npm/skooma@1.3.1/skooma.min.js"</code></pre>
<pre class="box"><code lang=js>import {html} from "https://cdn.jsdelivr.net/npm/nyooom/nyooom.js"</code></pre>
</section>
<section>
<p>
Calling any method on this object will generate an HTML node.
Calling any method on the <code>html</code> export will generate an HTML node.<br>
Passing in arguments is how you add children, set attributes and even do more advanced things.
</p>
<skooma-showcase preview="false">
<nyooom-showcase preview="false">
<code>
<div contenteditable="false">return html.div()</div>
<div contenteditable="false">return html.div("content")</div>
</code>
</skooma-showcase>
</nyooom-showcase>
<p>
Using the <code>component</code> helper from the <code>sckooma/observable.js</code> module
Using the <code>component</code> helper from the <code>nyooom/observable</code> module
makes it easier to see results on your page:
Just pass it a function that returns some DOM nodes, and it'll register a custom element for you.
</p>
<pre><code lang=js>import {component} from "https://cdn.jsdelivr.net/npm/skooma@1.3.1/state.min.js"
<pre class="box"><code lang=js>import {component} from "https://cdn.jsdelivr.net/npm/nyooom/observable.js"
const myComponent = () =&gt; html.div("Rendered Component")
component(myComponent) //Registers it as &lt;my-component&gt;</code></pre>
@ -171,17 +174,17 @@ component(myComponent) //Registers it as &lt;my-component&gt;</code></pre>
This works for strings, HTML elements, functions and even observable state containers.
</p>
<skooma-showcase preview="false">
<nyooom-showcase preview="false">
<code>
<div contenteditable="false">return html.span(
"Skooma ",
"Nyooom ",
html.u(
"is ",
html.b("cool")
)
)</div>
</code>
</skooma-showcase>
</nyooom-showcase>
</section>
<section>
@ -190,14 +193,14 @@ component(myComponent) //Registers it as &lt;my-component&gt;</code></pre>
If the value is an array, it'll get joined with spaces.
</p>
<skooma-showcase preview="false">
<nyooom-showcase preview="false">
<code>
<div contenteditable="false">return html.span({
id: "warning",
class: ["danger", "bold"],
})</div>
</code>
</skooma-showcase>
</nyooom-showcase>
</section>
<section>
@ -205,7 +208,7 @@ component(myComponent) //Registers it as &lt;my-component&gt;</code></pre>
Event listeners work just like attribute, except the value is a function:
</p>
<skooma-showcase code="false">
<nyooom-showcase code="false">
<code>
<div contenteditable="false">return html.button("Click Me!", {
click: event => {
@ -213,7 +216,7 @@ component(myComponent) //Registers it as &lt;my-component&gt;</code></pre>
}
})</div>
</code>
</skooma-showcase>
</nyooom-showcase>
<section>
<p class="big">
@ -228,7 +231,7 @@ component(myComponent) //Registers it as &lt;my-component&gt;</code></pre>
will be converted to strings.
</p>
<skooma-showcase>
<nyooom-showcase>
<code>
<div contenteditable="false">return html.div(
{ style: {
@ -241,13 +244,13 @@ component(myComponent) //Registers it as &lt;my-component&gt;</code></pre>
)
)</div>
</code>
</skooma-showcase>
</nyooom-showcase>
<p>
<code>dataset</code> converts its key-value pairs into <code>data-</code> attributes.
</p>
<skooma-showcase preview=false>
<nyooom-showcase preview=false>
<code>
<div contenteditable="false">return html.span(
{ dataset: {
@ -258,13 +261,13 @@ component(myComponent) //Registers it as &lt;my-component&gt;</code></pre>
"Heat from Fire"
)</div>
</code>
</skooma-showcase>
</nyooom-showcase>
<p>
<code>shadowRoot</code> will attach a shadow DOM to the newly created node.
</p>
<skooma-showcase code=false>
<nyooom-showcase code=false>
<code>
<div contenteditable="false">return html.div(
{ shadowRoot: [
@ -274,7 +277,7 @@ component(myComponent) //Registers it as &lt;my-component&gt;</code></pre>
"Light DOM text"
)</div>
</code>
</skooma-showcase>
</nyooom-showcase>
</section>
</section>
</section>
@ -283,17 +286,17 @@ component(myComponent) //Registers it as &lt;my-component&gt;</code></pre>
<h2>It's just JavaScript</h2>
<p>Skooma is entirely implemented as a light-weight JavaScript library.</p>
<p>Nyooom is entirely implemented as a light-weight JavaScript library.</p>
<p>
What this means is that there's no new syntax for things you already know how to do.
This means that there is no new syntax for things you already know how to do.
Functions like <code>filter</code> or <code>map</code> can be applied directly to your data,
nodes can be assigned to variables right as you create them,
common structures can be extracted into function and even passed around as arguments,
and the syntax is just the boring old javascript that most tools already understand.
</p>
<skooma-showcase code="false">
<nyooom-showcase code="false">
<code>
<div contenteditable="false">return html.ul(
["u", "b", "i"].map(
@ -303,16 +306,16 @@ component(myComponent) //Registers it as &lt;my-component&gt;</code></pre>
)
)</div>
</code>
</skooma-showcase>
</nyooom-showcase>
</section>
<section class="content-width">
<h2>State changes in Skooma</h2>
<h2>State changes in Nyooom</h2>
<pre><code lang=js>import {ObservableObject} from 'skooma/observable.js'</code></pre>
<pre class="box"><code lang=js>import {ObservableObject} from 'nyooom/observable'</code></pre>
<p class="big">
Skooma offers a series of state management classes it calls "observables".
<p>
Nyooom offers a series of state management classes it calls "observables".
Their purpose is to store one or more values and emit events when they are changed.
</p>
@ -322,17 +325,16 @@ component(myComponent) //Registers it as &lt;my-component&gt;</code></pre>
and they use a common protocol to work together.
</p>
<skooma-showcase code="false">
<nyooom-showcase code="false">
<code>
<div contenteditable="false">const counter = new State({value: 0})
counter.valueChanged = newValue =&gt;
console.log(`Value: ${newValue}`)
<div contenteditable="false">const counter = new State(0)
return html.buttonGroup(
html.button(
"Click Me! ",
html.span(counter),
html.span(
counter.compose(val =&gt; val ? val : "")
),
{
click() {
counter.value += 1
@ -348,7 +350,7 @@ return html.buttonGroup(
)
)</div>
</code>
</skooma-showcase>
</nyooom-showcase>
</section>
<section class="content-width">
@ -356,11 +358,11 @@ return html.buttonGroup(
<h2>Obligatory Todo list</h2>
<p>
This simple ToDo component uses nothing more than Skooma and
This simple ToDo component uses nothing more than Nyooom and
the stylesheets already on this page to save some boilerplate.
</p>
<skooma-showcase code="false">
<nyooom-showcase code="false">
<code>
<div contenteditable="false">const task = value =>
html.flexRow (
@ -398,18 +400,18 @@ return todo = html.flexColumn(
})
)</div>
</code>
</skooma-showcase>
</nyooom-showcase>
</section>
<section id="skooma-explained" class="content-width">
<h2>Skooma Explained</h2>
<section id="nyooom-explained" class="content-width">
<h2>Nyooom Explained</h2>
<h3>A bit of boring history</h3>
<p>
The <code>skooma/render.js</code> module traces its basic idea back to a Lua module.
The <code>nyooom/render.js</code> module traces its basic idea back to a <a href="https://github.com/darkwiiplayer/skooma">Lua module</a>.
The basic mechanism is the exact same, as the languages are very similar;
with the noteable difference that skooma.lua outputs text and uses a very
with the noteable difference that the Lua version outputs text and uses a very
lightweight DOM-like data-structure as an intermediary representation.
</p>
@ -422,7 +424,7 @@ return todo = html.flexColumn(
</p>
<p>
One design goal while further expanding the capabilities of skooma has been to preserve this original use-case.
One design goal while further expanding the capabilities of nyooom has been to preserve this original use-case.
The library is <i>small enough</i> that pulling it into a project just to generate a few nested DOM structures
here and there isn't an unjustifiable waste of application size.
This is also why the <code>render</code> module does not depend on the <code>observable</code>
@ -430,12 +432,12 @@ return todo = html.flexColumn(
</p>
<p>
The later addition of the <code>Obervable</code> module, and the ability of skooma to detect state objects and
The later addition of the <code>Obervable</code> module, and the ability of nyooom to detect state objects and
handle them specially to enable reactivity is what truly enables the library to be used on its own to build
simple and even moderately complex interactive components.
<br>
And with most of this extra complexity existing in a separate file,
the size impact on the core skooma library is very minimal, when
the size impact on the core nyooom library is very minimal, when
reactivity is not wanted, or an alternative mechanism for reactivity
is preferred.
</p>
@ -443,49 +445,49 @@ return todo = html.flexColumn(
<h3>Implementation</h3>
<p>
Skooma is based on a convenient wrapper around <code>document.createElement</code>
Nyooom is based on a convenient wrapper around <code>document.createElement</code>
made even more convenient by a <code>Proxy</code> to generate & populate DOM nodes.
</p>
<h3>Rationale & design principles</h3>
<p>
The design of skooma is based on the following assumption about web applications:
The design of nyooom is based on the following assumption about web applications:
</p>
<blockquote>
Most web application code can be modeled with simple abstractions.
The few cases that can't tend to be too complex for any general-purpose abstraction.
Most web application code can be modeled with simple abstractions.<br>
The few cases that can't tend to be too complex for any general-purpose abstraction anyway.
</blockquote>
<p>
Leading to a framework that focuses on the former group,
while giving developers the tools to handle the tricky bits without having to hack themselves out of the framework.
while giving developers the tools to handle the tricky bits without having to hack themselves out of the framework first.
</p>
<p>
One consideration that sets skooma apart from other alternatives,
One consideration that sets nyooom apart from other alternatives,
is the emphasis on being both easy to adopt, integrate, and even abandon.
</p>
<p>
While skooma provides some level of abstraction over native browser APIs, everything done via skooma is
While nyooom provides some level of abstraction over native browser APIs, everything done via nyooom is
still easy to mentally map onto the underlying APIs. This reduces the mental load of translating what the
code says, and what is happening to the website, creating a common mental model with vanilla javascript,
as well as other non-magic libraries and micro-frameworks.
</p>
<p>
This, in practice, means that adding some code that uses skooma to an existing project, integrating it with
This, in practice, means that adding some code that uses nyooom to an existing project, integrating it with
other technologies, and even removing it in parts or in whole from a project that has outgrown it, or from performance-critical
parts of an application that need even the last drop of performance squeezed out of the browser are all very
simple to achieve.
</p>
<p>
Even taking out certain aspects like reactivity, while still using skooma to generate DOM nodes that get manipulated
Even taking out certain aspects like reactivity, while still using nyooom to generate DOM nodes that get manipulated
manually in response to complex state-changes is as easy as replacing the state objects with primitive values
and writing the custom code to take their place.
</p>
<p>
Where other frameworks suck in their stomach and do their best to fit every use-case you could have,
skooma is happy to just step aside and make space for more specialised tools.
<!-- skooma: the framework that promotes body-acceptance -->
nyooom is happy to just step aside and make space for more specialised tools.
<!-- nyooom: the framework that promotes body-acceptance -->
</p>
</section>
</main>
@ -500,4 +502,4 @@ return todo = html.flexColumn(
</table>
</flex-row>
</footer>
</html>
</htmlt>

View file

@ -1,5 +1,5 @@
import {html,empty} from "https://cdn.jsdelivr.net/gh/darkwiiplayer/skooma-js@f79e7a9/skooma.js"
import {State} from "https://cdn.jsdelivr.net/gh/darkwiiplayer/skooma-js@f79e7a9/state.js"
import {html,nothing} from "nyooom/render"
import {ObservableValue,ObservableObject} from "nyooom/observable"
import element from "https://darkwiiplayer.github.io/easier-elements-js/easier-elements.js"
import hljs from 'https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/es/highlight.min.js';
import lang_html from "https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/es/languages/xml.min.js"
@ -55,7 +55,7 @@ const theme = html.link({
href: "https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/styles/github-dark.min.css"
})
element(class SkoomaShowcase extends HTMLElement {
element(class NyooomShowcase extends HTMLElement {
constructor() {
super()
this.attachShadow({mode: "open"})
@ -76,25 +76,9 @@ element(class SkoomaShowcase extends HTMLElement {
}
connectedCallback() {
this.classList.add("box")
this.shadowRoot.replaceChildren(
html.slot(),
html.span("🖉", {
class: "edit",
click: ({target: button}) => {
this.querySelectorAll("[contenteditable]")
.forEach(item => {
if (item.contentEditable == "true") {
item.contentEditable = "false"
button.classList.remove("editing")
this.format()
} else {
item.contentEditable = "true"
button.classList.add("editing")
item.innerText = item.innerText
}
})
}
}),
html.style(css),
...Array.from(document.styleSheets).map(sheet => sheet.ownerNode.cloneNode(true)),
theme.cloneNode(true),
@ -110,7 +94,7 @@ element(class SkoomaShowcase extends HTMLElement {
const code = this.querySelector("code").innerText
try {
const fn = new Function("html", "empty", "State", code)
const result = fn(html, empty, State)
const result = fn(html, nothing, ObservableValue)
this.error.replaceChildren()
this.output.innerHTML = hljs.highlight("html", result.outerHTML).value
this.preview.classList.toggle("hidden", this.getAttribute("preview") === "false")

View file

@ -11,7 +11,10 @@
& em {
font-style: unset;
color: var(--secondary-5);
color: var(--secondary-4);
@container style(--color-scheme: dark) {
color: var(--secondary-7);
}
}
}