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

skope

v0.5.0

Published

A sandboxed js-in-html UI framework

Downloads

1

Readme

Skope.js

A sandboxed js-in-html UI framework. The main goal of this library is to allow user generated content to use javascript in html safely. The idea behind this is if this is safe enough for user generated content, then it is also safe for any other possible usecases.

Having sandboxed js-in-html enables creating interactive html without permitting the use of all of the browsers's api, which would be dangerous if in the wrong hands. To use native browser api, wrapper functions should be provided to the app that use them, this would allow the app developer to sanitize and whitelist parameters to be used with the sensitive api.

The sandbox library does not use eval / Function under the hood, and therefore makes this library CSP friendly.

This allows, for example, content platforms (such as WordPress, Drupal, or any other CMS) to allow their users to embed dynamic elements in their content without having to worry about security.

This library makes html in REST api safe again!

Installation

npm i skope

Getting started

<!DOCTYPE html>
<html lang="en">
<head>
  <script src="https://cdn.jsdelivr.net/gh/nyariv/skope@latest/dist/defaultInit.js" type="module"></script>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/nyariv/skope@latest/dist/skopejs.css">
  <meta charset="UTF-8">
</head>
  <body skope s-cloak $my-var="'Hello World'">
    {{myVar}}
  </body>
</html>

Features

Variables

  <div $var1="'Hello'" $var2="'World'">
    {{var1}} {{var2}}
  </div>

Events

Trigger multiple times

  <button $var1="false" @click="var1 = !var1">{{var1 ? 'On' : 'Off'}}</button>

Trigger only once

  <button $var1="false" @click.once="var1 = !var1">{{var1 ? 'On' : 'Off'}}</button>

Save event callback promise to variable

  <div $var1="'none'">
    <button  @click$var1="await $delay(500); return Math.random()">Event value: {{var1}}</button>
  </div>

Attributes

  <style>
    .red {color: red}
  </style>
  <div :class="{red: true}">this is red</div>

s-cloak

This attribute is removed when the html is processed by skope. In the default stylesheet it is treated as display: none.

  <div s-clock>
    {{'this is hidden while app is loading'}}
  </div>

s-for

  <div> <span s-for="i in [1,2,3]"> {{i}} </span> </div

s-if

  <div $var1="false">
    <button @click="var1 = !var1">{{var1 ? 'On' : 'Off'}}</button>
    <div s-if="var1"> Hello World </div>
  </div>

s-show

This attribute adds a class .hide if true. In the default stylesheet it is treated as display: none.

  <div $var1="false">
    <button @click="var1 = !var1">{{var1 ? 'On' : 'Off'}}</button>
    <div s-show="var1"> Hello World </div>
  </div>

s-transition

This attribute will add classes based on a promise set to a variable, for each of its promise state:

  • .s-transition - always set for this directive
  • .s-transition-idle - set when the variable is undefined or is not a promise
  • .s-transition-active - set when the promise did not resolve or reject yet
  • .s-transition-done - set when the promise is resolved
  • .s-transition-error - set when the promise rejected
  <div $var1 $var2>
    <style>
      .s-transition span {
        display: none;
      }
      .s-transition-idle .idle {
        display: block;
      }
      .s-transition-active .active {
        display: block;
      }
      .s-transition-done .done {
        color: green;
        display: block;
      }
      .s-transition-error .error {
        color: red;
        display: block;
      }

      .loader {
        border: 2px solid white;
        border-top: 2px solid #ccc;
        border-radius: 50%;
        width: 14px;
        height: 14px;
        animation: spin .4s linear infinite;
      }

      @keyframes spin {
        0% { transform: rotate(0deg); }
        100% { transform: rotate(360deg); }
      }
    </style>

    <button @click$var1="await $delay(2000); if(Math.random() < .5) throw new Error('random error')">Trigger transition</button>
    <div s-transition="var1"> 
      <span class="idle">Idle</span>
      <span class="active"><div class="loader"></div></span>
      <span class="done">Done</span>
      <span class="error">Error</span>
    </div>

    <button @click$var2="await $delay(2000); if(Math.random() < .5) throw new Error('random error')">Trigger custom transition</button>
    <div $running
         class="s-transition"
         :class.s-transition-idle="(running = var2?.then(() => running = false, () => running = false)) === undefined"
         :class.s-transition-active="!!running"
         :class.s-transition-done="!running && var2?.then(() => true, () => false)"
         :class.s-transition-error="!running && var2?.then(() => false, () => true)"
    >
      <span class="idle">Idle</span>
      <span class="active"><div class="loader"></div></span>
      <span class="done">Done</span>
      <span class="error">Error: {{var2?.catch((e) => e.message)}}</span>
    </div>
  </div>

s-model

  <div $value="false">
    <label>Say hi <input type="checkbox" s-model="value"></label>
    <div s-show="value"> Hello World </div>
  </div>

s-text

  <div $text="'Hello World'">
    <label>Input <input type="text" s-model="text"></label>
    <div s-text="text"></div>
  </div>

s-html

  <div $html="'&lt;i&gt;Hello World&lt;/i&gt;'">
    <label>Input <input type="text" s-model="html"></label>
    <div s-html="html"></div>
  </div>

s-ref

This attribute will save the element as a special skope element object in a map of elements and their assigned names in the $refs global.

  <div $counter="0">
    <button @click="$refs.counterElem.text(++counter)">Add One</button>
    <div s-ref="counterElem">0</div>
  <div>

A skope element can also be a collection of elements which have a single api to act on all of them, similar to jQuery.

  <div $counter="0">
    <button @click="$refs.counterElems.val(++counter)">Add One</button>
    <input type="number" s-ref="counterElems" s-for="i in [0,0,0]">
  <div>

s-detached

Create a scope of html that does not inherit scopes from parent elements, and has it its own $refs object.

  <div $one="1">
    <div s-detached>
      {{typeof one === 'undefined' ? 'detached' : 'not detached'}}
    <div>
  <div>

s-static

An element with this attribute will not execute js in its nested elements, and will sanitize the html with safe element types only.

  <div s-static>
    <div $this-is-static="not static">
      {{thisIsStatic}}
    </div>
  </div>

Tenets

The main tenets of this library are ment to guarantee safety of this library, now and in the future, without having to update the library. These tenets are:

  1. Only safe ECMAScript features are whitelisted, everything else is either not supported or not allowed by default
  2. Only safe HTML5 elements, and elements defined by that app, are whitelisted, all other elements are not allowed by default
  3. Safety is guaranteed if a new unsafe ES feature or HTML element are introduced to web browsers because they are not, or cannot be, supported
  4. Whitelisted ES defaults will never include anything I/O bound, anything that could cause denial of service with a single expression, or anything that affects session behavior
  5. Whitelisted HTML defaults will never include elements that affect session behavior or make network requests (media and anchor tags are the exception).
  6. JS in a DOM element will never have more permissions than its parent, and have access only to its child elements, with the exception of app logic that allows this.