Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tagged templating, an alternative way to structure code that's all the rage #60

Merged
merged 2 commits into from
May 15, 2016

Conversation

tbranyen
Copy link
Owner

@tbranyen tbranyen commented Mar 19, 2016

This adds in support for building a "Virtual Tree" and passing it into
diffHTML. A Virtual Tree (or VTree) looks like this in diffHTML:

{
  "nodeName": "div",
  "nodeType": 1,
  "nodeValue": "",
  "attributes": [{ "name": "id", "value": "test" }],
  "childNodes": [{
    "nodeName": "#text",
    "nodeType": 3,
    "nodeValue": "Hello world!",
    "attributes": [],
    "childNodes": []
  }]
}

Which represents the following markup:

<div id="test">Hello world!</div>

It's allowed in any existing method like outerHTML and innerHTML. It's
really easy to use too. Check out a simple example:

import { outerHTML, html } from 'diffhtml';

const fixture = document.createElement('div');
const message = 'Hello world!';

outerHTML(fixture, html`<div id="test">${message}</div>`);

The coolest part about the above example is that the interpolation with
${...} allows for composition and event binding/sharing of non-string
based data that you would normally be bound to with an HTML string. For
instance the above could be rewritten to:

import { outerHTML, html } from 'diffhtml';

const fixture = document.createElement('div');
const message = () => 'Hello world!';

outerHTML(fixture, html`<div id="test">${message()}</div>`);

Now for a more complex example showing composition and re-rendering:

import { outerHTML, html } from 'diffhtml';

const partial = props => html`
  <div class=${props.test}></div>
`;

function render(date) {
  outerHTML(document.body, html`<body>
    <h1>Some new content diff/patched in!</h1>

    <p onclick=${e => console.log(e)}>
      <span>Current date: ${date}</span>
    </p>

    ${partial({ test: 'hello world' })}
  </body>`);
}

setInterval(function() {
  render(new Date().toLocaleString());
}, 1000);

render(new Date().toLocaleString());

I'll start working on a Babel transform as well to make the entire parse
time disappear. Performance-ahoy. Thx JSX, yo-yo, bel for inspiration
choo-choo.

Related changes:

  • Updated dependencies
  • While testing you can skip coverage with SKIP_COV=true env var
  • Fix bug where newHTML was set for non-string input
  • No longer cleans up in the middle of rendering, which broke VDOM inputs
  • Ensures that non-string attributes (aka props for now) are removed properly
  • Added more tests

@tbranyen tbranyen changed the title Tagged templating is all the rage, so why not WIP: Tagged templating is all the rage, so why not Mar 19, 2016
@tbranyen tbranyen force-pushed the add-tagged-template-function branch 2 times, most recently from 1c8f2ab to 838a805 Compare May 13, 2016 06:11
@tbranyen
Copy link
Owner Author

tbranyen commented May 13, 2016

There's something strange happening where certain elements aren't getting protected like they should be.

Edit: Before I was cleaning memory in the middle of renders which never mattered until HTML parsing could happen multiple times for nested tagged template strings. This has since been corrected.

@tbranyen tbranyen changed the title WIP: Tagged templating is all the rage, so why not Tagged templating, an alternative way to structure code that's all the rage May 14, 2016
@tbranyen tbranyen force-pushed the add-tagged-template-function branch 2 times, most recently from 6ced6da to 0268711 Compare May 14, 2016 22:18
This adds in support for building a "Virtual Tree" and passing it into
diffHTML. A Virtual Tree (or VTree) looks like this in diffHTML:

    {
      "nodeName": "div",
      "nodeType": 1,
      "nodeValue": "",
      "attributes": [{ "name": "id", "value": "test" }],
      "childNodes": [{
        "nodeName": "#text",
        "nodeType": 3,
        "nodeValue": "Hello world!",
        "attributes": [],
        "childNodes": []
      }]
    }

Which represents the following markup:

    <div id="test">Hello world!</div>

It's allowed in any existing method like outerHTML and innerHTML. It's
really easy to use too. Check out a simple example:

    import { outerHTML, html } from 'diffhtml';

    const fixture = document.createElement('div');
    const message = 'Hello world!';

    outerHTML(fixture, html`<div id="test">${message}</div>`);

The coolest part about the above example is that the interpolation with
`${...}` allows for composition and event binding/sharing of non-string
based data that you would normally be bound to with an HTML string. For
instance the above could be rewritten to:

    import { outerHTML, html } from 'diffhtml';

    const fixture = document.createElement('div');
    const message = () => 'Hello world!';

    outerHTML(fixture, html`<div id="test">${message()}</div>`);

Now for a more complex example showing composition and re-rendering:

    import { outerHTML, html } from 'diffhtml';

    const partial = props => html`
      <div class=${props.test}></div>
    `;

    function render(date) {
      outerHTML(document.body, html`<body>
        <h1>Some new content diff/patched in!</h1>

        <p onclick=${e => console.log(e)}>
          <span>Current date: ${date}</span>
        </p>

        ${partial({ test: 'hello world' })}
      </body>`);
    }

    setInterval(function() {
      render(new Date().toLocaleString());
    }, 1000);

    render(new Date().toLocaleString());

I'll start working on a Babel transform as well to make the entire parse
time disappear. Performance-ahoy. Thx JSX, yo-yo, bel for inspiration
choo-choo.

Related changes:

- Updated dependencies
- While testing you can skip coverage with SKIP_COV=true env var
- Fix bug where newHTML was set for non-string input
- No longer cleans up in the middle of rendering, which broke VDOM inputs
- Ensures that non-string attributes (aka props for now) are removed properly
- Added more tests
There was a test that did not put a `uuid` property on two descriptors
while testing the virtual dom passing to outerHTML. It never triggered
an error in the past due to lucky happenstance, but now I've tracked and
fixed it.
@tbranyen tbranyen force-pushed the add-tagged-template-function branch from 0268711 to 4272d8f Compare May 15, 2016 05:50
@tbranyen tbranyen merged commit 7c83cda into master May 15, 2016
@tbranyen tbranyen deleted the add-tagged-template-function branch May 15, 2016 05:53
@jamesplease
Copy link

🎉 💃 👯 🍰

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants