npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

thescribe

v0.1.1

Published

HTML agnostic, declarive and reactive way to manipulate DOM

Downloads

49

Readme

Thescribe

HTML agnostic, declarive and reactive way to manipulate DOM

Thescribe is not production ready yet but feel free to install and experiment with it:

npm install thescribe

Motivation

Frameworks like React, Angular & Vue are great but are they answer to all the problems? I doubt it. They're good at what they're meant to do - make developing rich, highly reactive web applications easier. But most web applications aren't highly reactive and these frameworks come at a cost for all three: users, developers and also business. Most web pages require only certain part of them to be reactive, some just need to validate user inputs and few of them doesn't require it at all. I can't count all the websites made mostly from forms (or even simple blogs) and still built on top of React.

I like to start my projects as "MPA" (Multi-page application as I call it opposed to SPA). It's easier, quicker, doesn't requires much setup and technical decisions so I can focus on business logic and get faster feedback. But as the project grows up I often rewrite it to SPA (Single-page application). I strongly believe it's not because frameworks like React are so great, I rather think it's because tooling for such web apps is lacking. Imperative DOM manipulations with jQuery and synchronizing DOM with state can be such a pain. Thescribe is an attempt to change it and make developing reactive websites simpler and faster without affecting your whole project structure nor revolutionizing web. Render your HTML on the server, describe which parts of your websites depends on app's state, declare state manipulations and let Thescribe take care of the rest.

Goals

  • easy to pick up
  • small size
  • fast
  • easy to integrate with existing libs

Tutorial

Just a quick showcase of how Thescribe works. We'll create a simple counter app

Let's start with HTML:

<!DOCTYPE html>
<html>
<head>
  <title>Counter app</title>
</head>
<body>
  <div id="root">
    <div data-component="counter">
      <h1 data-target="count"></h1>
      <button data-factor="increment">Increment</button>
    </div>
  </div>
  <script src="/path/to/your/script.js"></script>
</body>
</html>

Component is the main block of your application. It holds its state and manages targets and factors.

Target is the part of component which is reactive. It'll react to changes of state and automatically update its content and attributes. It's worth noting that Thescribe is smart enough to react to only these parts of state which are necessary to update itself so no matter how big your state is nor how many targets your component has your updates will be fast.

And finally Factor is the part which will trigger your state changes. It can be a button with on-click event, an input with on-change or any other element with any event type browsers allow.

So it's finally time to define our component

import { Application, defineComponent } from 'thescribe'

const counterComponent = defineComponent(
  {
    // initial state of our application
    state: {
      counter: 0,
    },

    // definition of our targets
    targets: {
      // name of our target (data-target="count" in HTML)
      count: {
        // content of our target (escaped by default)
        text: state => `The count is ${state.count}`,
        // HTML attributes of our target, as our counter will reach a value of 10 it'll change its color to green
        attribute: state => ({
          title: state.count === 0 ? 'nothing' : 'something',
          style: {
            color: state.count >= 10 && 'green',
          },
        }),
        // a special effect to deal with CSS classes.
        // When `state.count` hits 10 it'll add `large` and remove `small` class from the target.
        classes: state => ({
          large: state.count >= 10,
          small: state.count < 10,
        }),
      },
    },

    // definition of our factors
    factors: {
      // name of our factor (data-factor="increment" in HTML)
      increment: {
        click: (event, state) => {
          // we just need to mutate our state and DOM will update automatically
          state.count += 1
        },
      },
    },
  },
)

// define app object and register previously defined component
const app = new Application(document.getElementById('root'))
app.registerComponent(
  'counter', // (data-component="counter" in HTML)
  counterComponent,
)

Project state

  • [ ] make it work (in progress)
  • [ ] make it right
  • [ ] make it fast

Incoming features

  • [x] connect components dynamically on DOM changes
  • [x] state initialization based on DOM
  • [ ] lifecycle methods
  • [ ] external state
  • [ ] a way to communicate between components
  • [ ] scope targets and factors to only one component to make nested components possible
  • [ ] performant function to render HTML