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

design-to-code

v1.0.2

Published

A set of utilities to assist in creating web UI

Downloads

9

Readme

Design to Code

Design to Code is a library agnostic specific set of utilities to assist in creating web UI.

JavaScript   TypeScript

Installation

npm i --save design-to-code

Concepts

JSON Schema

JSON schema are used by Design to Code libraries for generating data and creating UI. They have been extended to provide additional hooks for plugin systems in the Design to Code libraries. When providing a dictionary of JSON schema, use the id as a key, this is required for utilities to quickly access the correct JSON schema.

Nesting data

To identify nesting structures in the JSON schemas, such as with composable components, use the linkedDataSchema export from the design-to-code package which defines the interface expected for the link and adds a property key to identify this section of data as linked data.

Example JSON Schema with linked data properties:

import { linkedDataSchema } from "design-to-code";

export default {
    $schema: "http://json-schema.org/schema#",
    title: "Component with nested properties",
    type: "object",
    id: "nestable-component",
    properties: {
        children: {
            ...linkedDataSchema,
            title: "Children",
            type: "string"
        },
    }
}

Although JSON schema can be written in JSON, it is recommended creating the schema as a data blob in a JavaScript or TypeScript file so that it can use the provided helper exports.

Message system

Design to Code components rely on including a secondary script which contains a web worker called the message system.

This worker performs all of the data manipulation and provides a navigational data structure based on data passed.

Sending and receiving messages

There is a secondary export, MessageSystem, which must be instantiated with the location on the server of the web worker. The file is located at design-to-code/message-system.min.js. This is then passed to various components that are part of the tooling package to sync data and navigation.

Example implementation:

import { MessageSystem } from "design-to-code";

let messageSystem;

// Your JSON schema
const mySchema = {
    id: "my-schema",
    type: "object",
    properties: {
        foo: {
            type: "string"
        }
    }
}

if (window.Worker) {

    messageSystem = new MessageSystem({
        // The string location of the file on the server or the Worker instance.
        // If using webpack, include it in the entry section of the config.
        // Alternatively if instantiating the web worker with the webpack worker-loader,
        // simply use the Worker instance that has been imported
        webWorker: "message-system.min.js",

        // your data dictionary to initialize with (you may only need a single item)
        dataDictionary: [
            {
                dataDictionaryKey1: {
                    schemaId: mySchema.id,
                    data: {
                        foo: "Hello world"
                    },
                },
            },
            "dataDictionaryKey1",
        ],

        // your dictionary of schemas to validate data in the dictionary
        schemaDictionary: {
            [mySchema.id]: mySchema,
        },
    });
}

The dataDictionary and the schemaDictionary are not required when creating the instance of the message system but can be provided for a single point of intialization.

If initialization occurs later, the following method can be used:

messageSystem = new MessageSystem({
    webWorker: "message-system.min.js",
});

...

messageSystem.initialize({
    dataDictionary: myDataDictionary,
    schemaDictionary: mySchemaDictionary,
});

Initialization message

To re-initialize the message system an initialization message can be sent which requires a dataDictionary and schemaDictionary to be provided.

Example:

import { MessageSystemType } from "design-to-code";

...

messageSystem.postMessage({
    type: MessageSystemType.initialize,
    dataDictionary: myDataDictionary,
    schemaDictionary: mySchemaDictionary
});

Custom messages

It is possible to send custom messages, all that is required is the data being sent includes the type MessageSystemType.custom.

Example:

import { MessageSystemType } from "design-to-code";

...

messageSystem.postMessage({
    type: MessageSystemType.custom,
    myMessage: "Hello world"
});

Data utilities

Data utilities are used for the various data manipulations in the message system, they are also provided as exports.

Generating data from JSON schema

Data may be generated from a JSON schema using the getDataFromSchema export. This will only generate the required items as dictated by the JSON schema, and will always choose the first potential match in any situation, for example if a property is an enum and is required, it will add the first value in the enum list.

An example of generating data from the design-to-code package:

import { getDataFromSchema } from "design-to-code";

const data = getDataFromSchema(schema);

Mapping data

Data from the dictionary of data can be mapped with a helper mapDataDictionary. This will allow you transform the data dictionary into another type of data structure by writing a helper. For example, if the data dictionary represented React component props, you could write a mapper using the React createElement function and return a functional React component.

The mapDataDictionary export takes an object with the following properties:

  • dataDictionary - A dictionary of data, this is similar to other data dictionary formats in this library but instead of specifying a root data item, it is the dictionary only.
  • dataDictionaryKey - This should be the root data items key.
  • schemaDictionary - This should be the dictionary of JSON schemas where each schema is identified in the object by its id which is used as a key.
  • mapper - The function provided that maps the data.

The mapping function that should be provided as the mapper in the mapDataDictionary argument accepts as its argument an object with the following properties:

  • data - The raw unchanged data.
  • resolvedData - Data that has been run through the mapper before.
  • schema - The JSON schema that maps to this piece of data, it should validate against the data property.

Example:

import { mapDataDictionary } from "design-to-code";

const mappingFunction = function(config) {
    return config.resolvedData;
}

const mappedData = mapDataDictionary({
    dataDictionary: {
        "root": {
            schemaId: "foo",
            data: {
                greeting: "Hello world"
            }
        }
    },
    dataDictionaryKey: "root",
    schemaDictionary: {
        foo: {
            id: "foo",
            type: "object"
        }
    },
    mapper: mappingFunction
});

The expected result:

{
    greeting: "Hello world"
}

Mapping Web Component definitions

Web components can be described with the TypeScript interface WebComponentDefinition or the JSON schema webComponentSchema, available as named exports from design-to-code.

Data that maps to these definitions can be passed as an argument to the mapWebComponentDefinitionToJSONSchema utility. This will generate an array of JSON schemas (one for each available tag) that the tooling can use.

Example:

import { mapWebComponentDefinitionToJSONSchema } from "design-to-code";

const myWebComponentJSONSchema = mapWebComponentDefinitionToJSONSchema(myWebComponentDefinition);

Validation

Validation is treated as optional by the message system but is available as a utility. This is done in case other validation methods are used as validators are decently sized packages and there may be validation scenarios that are not covered by standard JSON schema validation.

To facilitate ease of use however, the export AjvMapper is provided which utilizes the ajv library.

Example:

import { AjvMapper, MessageSystem } from "design-to-code";

let messageSystem: MessageSystem;
let ajvMapper: AjvMapper;

if ((window as any).Worker) {
    messageSystem = new MessageSystem({
        ...
    });
    ajvMapper = new AjvMapper({
        messageSystem: messageSystem,
    });
}

If necessary it is possible to make a custom validator. The AjvMapper can be used as a guide for mapping the pathing values and error messages to a format the message system can accept.