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

dom-to-model

v2.0.2

Published

maps a page dom content to a data model

Downloads

2

Readme

dom-to-model

build:? npm npm npm

It acts like an API adapter for an existing website and allows reconstructing a data model from its page content by mapping DOM elements to user-defined models. It supports mapping a single model or collection, as well as recursive mapping for props that represent other models or collections.

Table of Contents

Install

npm install --save dom-to-model

require

const { domToModel } = require('dom-to-model');

import

import { domToModel } from 'dom-to-model';

Intro

To use the library, you need to build your data model maps around an existing web page DOM. Each model has properties and each property holds a value that might be a primitive value (number, string, boolean), a list of values, an object (another model) or a list of models.

Prop Map

Defines the model property map schema. It has 4 types:

Value Prop Map

map prop to the content of an element

Schema
{
  "propType": "value",
  "map": {
    "dataType": "string|number|boolean",
    "path": "#some-id .some-class"
  }
}
Example
<span id="test1234">test data</span>
{
  "propType": "value",
  "map": {
    "dataType": "string",
    "path": "#test1234"
  }
}

map prop to a data attribute

Schema
{
  "propType": "value",
  "map": {
    "dataType": "string|number|boolean",
    "path": "#some-id .some-class",
    "dataAttr": "some-name"
  }
}
Example
<span id="test" data-content="1234">test data</span>
{
  "propType": "value",
  "map": {
    "dataType": "number",
    "path": "#test",
    "dataAttr": "content"
  }
}

List Prop Map

map a prop to a list of values

Schema
{
  "propType": "list",
  "map": {
    "itemDataType": "string|number|boolean",
    "itemPath": "#someId .someClass"
  }
}
Example
<ul id="test">
  <li>val 1</li>
  <li>val 2</li>
  <li>val 3</li>
</ul>
{
  "propType": "list",
  "map": {
    "itemDataType": "string",
    "itemPath": "ul#test li"
  }
}

Nested Model Prop Map

a model prop can be another model

Schema
{
  "propType": "model",
  "map": {
    "props": {
      "prop1": {
        /* value, model or list map */
      },
      "prop2": {
        /* value, model or list map */
      }
    }
  }
}
Example
<div class="employee">
  <span class="name">some name</span>
  <span class="age">33</span>
</div>
{
  "propType": "model",
  "map": {
    "props": {
      "name": {
        "propType": "value",
        "map": {
          "dataType": "string",
          "path": ".employee .name"
        }
      },
      "age": {
        "propType": "value",
        "map": {
          "dataType": "number",
          "path": ".employee .age"
        }
      }
    }
  }
}

Nested Model Collection Prop Map

a model prop can be a collection of other models.

Schema
{
  "propType": "list",
  "map": {
    "itemDataType": "model",
    "itemPath": "#somePath",
    "itemMap": {
      "props": {
        "propName": {
          "propType": "value",
          "map": {
            "dataType": "string",
            "path": "#someId .someClass"
          }
        }
      }
    }
  }
}
Example
<ul class="employees">
  <li>
    <span class="name">employee 1</span>
    <span class="age">33</span>
  </li>
  <li>
    <span class="name">employee 2</span>
    <span class="age">44</span>
  </li>
  <li>
    <span class="name">employee 3</span>
    <span class="age">55</span>
  </li>
</ul>
{
  "propType": "list",
  "map": {
    "itemDataType": "model",
    "itemPath": "ul.employees li",
    "itemMap": {
      "props": {
        "name": {
          "propType": "value",
          "map": {
            "dataType": "string",
            "path": ".name"
          }
        },
        "age": {
          "propType": "value",
          "map": {
            "dataType": "number",
            "path": ".age"
          }
        }
      }
    }
  }
}

Model Map

defines the whole model map that composes model prop maps.

Schema
{
  "mapType": "model",
  "props": {
    "propName1": {
      "propType": "value",
      "map": {
        /* value prop map */
      }
    },
    "propName2": {
      "propType": "list",
      "map": {
        /* list prop map */
      }
    }
  }
}
Example
<ul class="employee">
  <span class="name">employee name</span>
  <span class="age">33</span>
  <ul class="promotions">
    <li>promotion 1</li>
    <li>promotion 2</li>
    <li>promotion 3</li>
  </ul>
</ul>
{
  "mapType": "model",
  "props": {
    "name": {
      "propType": "value",
      "map": {
        "dataType": "string",
        "path": ".employee .name"
      }
    },
    "age": {
      "propType": "value",
      "map": {
        "dataType": "number",
        "path": ".employee .age"
      }
    },
    "promotions": {
      "propType": "list",
      "map": {
        "itemDataType": "string",
        "itemPath": ".employee ul.promotions li"
      }
    }  
  }
}

Model Collection Map

defines a model collection map by using the same schema of a list prop combined with the model map.

Schema
{
  "mapType": "collection",
  "itemPath": "#path-to-collection-model-item",
  "itemMap": {
    "props": {
      "propName1": {
        "propType": "value",
        "map": {
          /* value prop map */
        }
      },
      "propName2": {
        "propType": "list",
        "map": {
          /* list prop map */
        }
      }
    }
  }
}
Example
<ul class="employees">
  <li class="employee">
    <span class="name">employee 1</span>
    <span class="age">33</span>
  </li>
  <li class="employee">
    <span class="name">employee 2</span>
    <span class="age">44</span>
  </li>
  <li class="employee">
    <span class="name">employee 3</span>
    <span class="age">55</span>
  </li>
</ul>
{
  "mapType": "collection",
  "itemPath": "ul.employees li.employee",
  "itemMap": {
    "props": {
      "name": {
        "propType": "value",
        "map": {
          "dataType": "string",
          "path": ".name"
        }
      },
      "age": {
        "propType": "value",
        "map": {
          "dataType": "number",
          "path": ".age"
        }
      }
    }
  }
}

domToModel(url, modelMap)

After building your model maps, you can use the library main function to load dom into models. It accepts the page url that contains the dom and a model json map.

Mapping a model

const { domToModel } = require('dom-to-model');

const modelMap = require('./path_to_model_map.json');

const url = 'http://url_to_dom';

const model = await domToModel(url, modelMap);

Mapping a collection

const { domToModel } = require('dom-to-model');

const collectionMap = require('./path_to_collection_map.json');

const url = 'http://url_to_dom';

const models = await domToModel(url, collectionMap);

Demo: IMDB Movies

I built a small demo for the project here you can use like below:

IMDB Movie Model

const { demo: { imdbMovie } } = require('dom-to-model');

imdbMovie({ id: 'tt0232500' });

will log

{
  id: 'tt0232500',
  title: 'The Fast and the Furious',
  originalTitle: null,
  year: 2001,
  description: "Los Angeles police officer Brian O'Conner must decide where his loyalty really lies when he becomes enamored with the street racing world he has been sent undercover to destroy.",
  duration: '1h 46min',
  releaseDate: '22 June 2001 (USA)',
  storyLine: "Los Angeles street racer Dominic Toretto falls under the suspicion of the LAPD as a string of high-speed electronics truck robberies rocks the area. Brian O'Connor, an officer of the LAPD, joins the ranks of Toretto's highly skilled racing crew undercover to convict Toretto. However, O'Connor finds himself both enamored with this new world and in love with Toretto's sister, Mia. As a rival racing crew gains strength, O'Connor must decide where his loyalty really lies.",
  boxOffice: {
    budget: '$38,000,000',
    oppeningWeekendUsa: '$40,089,015,',
    grossUsa: '$144,533,925'
  },
  cast: [
    { actor: 'Paul Walker', role: "Brian O'Conner" },
    { actor: 'Vin Diesel', role: 'Dominic Toretto' },
    { actor: 'Michelle Rodriguez', role: 'Letty' },
    { actor: 'Jordana Brewster', role: 'Mia Toretto' },
    { actor: 'Rick Yune', role: 'Johnny Tran' },
    { actor: 'Chad Lindberg', role: 'Jesse' },
    { actor: 'Johnny Strong', role: 'Leon' },
    { actor: 'Matt Schulze', role: 'Vince' },
    { actor: 'Ted Levine', role: 'Sgt. Tanner' },
    { actor: 'Ja Rule', role: 'Edwin' },
    { actor: 'Vyto Ruginis', role: 'Harry' },
    { actor: 'Thom Barry', role: 'Agent Bilkins' },
    { actor: 'Stanton Rutledge', role: 'Muse' },
    { actor: 'Noel Gugliemi', role: 'Hector' },
    { actor: 'R.J. de Vera', role: 'Danny Yamato' }
  ]
}

IMDB Movie Titles Collection

const { demo: { imdbMovieTitles } } = require('dom-to-model');

imdbMovieTitles({ year: 2019 });

will log

 [
  {
    title: 'The Mandalorian',
    runtime: '40 min',
    description: 'The travels of a lone bounty hunter in the outer reaches of the galaxy, far from the authority of the New Republic.'
  },
  {
    title: 'The Boys',
    runtime: '60 min',
    description: 'A group of vigilantes set out to take down corrupt superheroes who abuse their superpowers.'
  },
  {
    title: 'His Dark Materials',
    runtime: '60 min',
    description: "A young girl is destined to liberate her world from the grip of the Magisterium which represses people's ties to magic and their animal spirits known as daemons."
  },
  {
    title: 'Virgin River',
    runtime: '44 min',
    description: 'After seeing an ad for a midwife, a recently widowed big-city nurse moves to the redwood forests of northern California, where she meets an intriguing man.'
  },
  {
    title: 'Mosul',
    runtime: '101 min',
    description: 'A police unit from Mosul fight to liberate the Iraqi city from thousands of ISIS militants.'
  },
  {
    title: 'Knives Out',
    runtime: '130 min',
    description: 'A detective investigates the death of a patriarch of an eccentric, combative family.'
  },
  {
    title: 'The Witcher',
    runtime: '60 min',
    description: 'Geralt of Rivia, a solitary monster hunter, struggles to find his place in a world where people often prove more wicked than beasts.'
  },
  // ...

Build

grunt build
  domToModel(url, modelMap)
    ✓ map dom to a model object (7710ms)
    ✓ map dom to a model collection (8842ms)
    ✓ throw an error if url is missing
    ✓ throw an error model map is missing
    ✓ throw an error model type is unknown

  .fetchDom(url)
    ✓ fetch dom of a page and resolve with jQuery (1011ms)

  mapCollection(jQuery, collectionMap)
    ✓ throw an error if prop data map is not a valid scheme (174ms)
    ✓ map dom to a model object (277ms)

  mapElementToValue(element, dataType, dataAttr)
    ✓ return null when element does not exist (109ms)
    ✓ map an input element (98ms)
    ✓ map a text element (127ms)
    ✓ map an element with number value (80ms)
    ✓ map an element with boolean value (49ms)
    ✓ map a prop from a data attribute (101ms)

  mapModel(jQuery, modelMap)
    ✓ throw an error if prop data map is not a valid scheme (100ms)
    ✓ map dom to a model object (436ms)

  mapPropToElement(jQuery, propMap)
    ✓ throw an error if prop data map is not a valid scheme (104ms)
    ✓ map a prop from a text element (115ms)
    ✓ map a prop from an input element (100ms)
    ✓ map a prop from a data attribute (87ms)
    ✓ map a prop from a list of elements to an array (136ms)
    ✓ return a prop to an empty array if list does not exist (120ms)
    ✓ maps a prop from an element (130ms)


  23 passing (20s)

----------------------|---------|----------|---------|---------|-------------------
File                  | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------------------|---------|----------|---------|---------|-------------------
All files             |      97 |    91.49 |     100 |    97.7 |                   
 domToModel.js        |   94.44 |    91.67 |     100 |   93.75 | 37                
 fetchDom.js          |     100 |      100 |     100 |     100 |                   
 mapCollection.js     |   92.86 |       75 |     100 |     100 | 24                
 mapElementToValue.js |     100 |      100 |     100 |     100 |                   
 mapModel.js          |     100 |      100 |     100 |     100 |                   
 mapPropToElement.js  |    97.3 |    88.24 |     100 |   96.88 | 79                
----------------------|---------|----------|---------|---------|-------------------

Done.

License

The ISC License. Full License is here