smizell/halpert — pull request #1 by smizell (2014-02-09 05:52:24+00:00)
Title: Refactor Library to Support Other Formats

Currently, halpert is set up to just support going from HTML+RDFa to HAL+JSON. I worked on extracting some of this functionality so that multiple formats can be supported. This is my proposed plan for it along with a feature branch with what I currently have. Any comments are appreciated.

## Data Structure

For each format that is supported, there are two functions needed: one for parsing the format and one for building the format. Currently, halpert only supports parsing HTML and building HAL+JSON.

To do this parsing and building, I had to come up with a general object tree that the parses returned and the builders accepted. For what I have so far, I've come up with this:

```javascript
{
curies: [], // or namespaces? vocabularies?
properties: {}
links: {},
embedded: {},
queries: {},
forms: {}
}
```

Each `embedded` resource MUST be an array of object literals that look like this:

```javascript
{
properties: {}
links: {},
queries: {},
forms: {}
}
```

So far, I have not implemented queries and forms in what I have for HTML and HAL, but I will. What the above structure allows for is a generalized format that can be derived from any type of object. Here is an example that is built from the HTML I have:

```JSON
{
"curies": [
{
"name": "ea",
"href": "http://example.com/docs/rels/"
}
],
"properties": {
"currentlyProcessing": "14",
"shippedToday": "20"
},
"links": {
"self": [{ "href": "/orders" }],
"next": [{ "href": "/orders?page=2" }],
"ea:admin": [
{
"href": "/admins/2",
"title": "Fred"
},
{
"href": "/admins/5",
"title": "Kate"
}
]
},
"embedded": {
"ea:order": [
{
"properties": {
"total": "30.00",
"currency": "USD",
"status": "shipped"
},
"links": {
"self": [{ "href": "/orders/123" }],
"ea:basket": [{ "href": "/baskets/98712" }],
"ea:customer": [{ "href": "/customers/7809" }]
}
},
{
"properties": {
"total": "20.00",
"currency": "USD",
"status": "processing"
},
"links": {
"self": [{ "href": "/orders/124" }],
"ea:basket": [{ "href": "/baskets/98713" }],
"ea:customer": [{ "href": "/customers/12369" }]
}
}
]
}
}
```

## API

I have also worked on changing up the API significantly. Now, it allows for this:

```javascript
var halObj = Halpert.convert(html).from('html').to('hal_json');
```

the `.convert` function loads the initial data, `.from` parses it, and `.to` builds the HAL object. Although those are the only ones supported, it means that this could be done once Siren is supported:

```javascript
var sirenObj = Halpert.convert(html).from('html').to('siren');
```

It also allows for not using a parser if you are doing the parsing yourself, which would be:

```javascript
var sirenObj = Halpert.convert(customObj).to('siren');
```

I think the next step would be to have a function for registering formats that are not supported by this library. Something like:

```javascript
Halpert.register('cj', cj.parser, cj,builder);
```

## Final thoughts

This really makes the halpert library a generic wrapper for parsers and builders. My thought is that if this is the way to go, the generalized format outlined above needs to be well done. Additionally, if I'm doing it this way with this generalized format, am I creating _another_ hypermedia format that just supports all of the possible hypermedia factors?

Thoughts?