• Hybrid HTML/DOM Editors

    This document expects the reader is professionally experienced in the authoring of Web content.

    Knowledge of the DOM, HTML and the difference between the two are pre-requisite.

    This document avoids prescribing the larger User eXperience of a Hybrid Editor, and merely (hah! merely) attempts to define the broad categories of editing modalities, and capabilities a Hybrid Editor provides.

    Further this document attempts to define a performant and maintainable surface area upon which Hybrid Editors may be
    built.

    Where possible this document is descriptive rather than specific.

  • Q & A

    Dear reader. Please Ask Questions Under this Section.

  • Short Glossary of Terms

  • HTML Editor

  • Canvas

  • DOM Editor

  • Code Projection

  • Typically tools combining HTML and DOM editing into one authoring tool have been met with negative reaction.

    This is not without reason. A hybrid HTML/DOM Editor has many challenges and failure to meet these challenges leads to a sub-satisfactory work-flow.

    Some of these challenges are detailed and explored:

  • Authors:

    • Collin Miller
  • Q: How do I Ask a Question?

  • HTML Editors

    An HTML Editor is a typical Text editor. Any program capable of opening a text file, allowing manipulation of it’s text content, and saving the changes to the file may be used as an HTML editor.

    Many applications go further:

    • highlighting the tokens of HTML while the author edits
    • auto completing closing tags of html elements
    • many other nice things
  • Canvas

    The direct or conceptual rendering of a Document Object Model to a 2d plane. A Typical Canvas is a web browser. Any subsection of the DOM may be referred to as a Canvas.

  • DOM Editors

    A DOM Editor is a special program capable of rendering a Document Object Model Object graph to a Canvas. A DOM Editor facilitates updating the edges and nodes of that graph while re-painting the Canvas. Most Web Browsers are DOM Editors. The specification for the DOM includes an API for editing DOM graphs with methods such as:

    • document.createElement(nodeName)
    • Node#appendChild(childNode)
    • document.createAttribute(attributeName)
    • and many others…

    DOM Editors may go further, facilitating creation and manipulation of a DOM graph without directly using the API methods. High level modalities such as “Drag and Drop” may be used. Visual lists of Node types may be shown to content authors. And text may be edited directly with a keyboard. These Editors are generally known by the term: WYSIWYG, or “What You See is What You Get”.

  • Code Projection / Source Mapping

    Code projection is the direct mapping of source code from an HTML Editor to a DOM Editor.

    A sub-component of Code Projection is Source Mapping, or the reverse mapping of DOM Elements to character positions in the HTML Editor.

    There may not be an 1-to-1 mapping of the tags written in the HTML source to the Nodes in the Canvas.

    In the course of projection some elements may be transformed, expanded, or exploded to present alternate, extended, or generated content.

    This transformation capability will be explored further in the Plugins section.

    It is ultimately the combination of Code Projection and Source Mapping that define the Hybrid Editor as a unique system.

    The Quality of the Code Projection is of ultimate importance to the function, development, and maintainability of a Hybrid Editor.

  • Source to “Source” Mapping

    • Directly mapping DOM elements to HTML source locations.
    • Directly mapping HTML source locations to DOM elements.
  • Minimal Changes

    • Minimal changes to DOM tree when making changes to source HTML
    • Minimal changes to source HTML when making changes to DOM.
  • Editor “Chrome”

  • Plugins

    Allowing plugins to manipulate the projection between HTML and DOM.

  • Data

  • Repeating Elements

  • Transclusions

  • Conditional Content

  • A: Ask a question by creating a new sub-item in the Q & A item
    . Hopefully somebody will answer it quickly. If you see an unanswered question and you know the answer, answer it.

  • DOM —> HTML Mapping

    Knowing which character ranges in the HTML source correspond to which DOM elements in the Graph is useful for the following capabilities:

    • Clicking on an Element in the Canvas and moving the selection of the HTML Editor to the position in the source that defines that Element.

    And more importantly:

    • Knowing where to place new HTML source when changes are made to the Canvas

    This problem has been solved by Mozilla in their “Slowparse” module: https://github.com/mozilla/slowparse

    Contrary to the name, “Slowparse” is fast. Fast enough to parse a 700+ line text file on 2013 hardware in > 10ms. On other hardware this time may be in the 10-60ms range. This makes Slowparse “Fast Enough” for typical workflows where source files can be kept under several hundred lines long. On the slower end of this scale Slowparse maybe ‘debounced’ to only run after user input has halted for a fraction of a second.

    Slow parse emits a DOM Tree in which Nodes and Attributes are given a parseInfo expando detailing the beginning and ending positions in the source text.

    Further performance might be attained by implementing a re-entrant parser. Rather than parsing the entire document each time the source code changes, the parseInfo could be used to determine what part of the DOM corresponds to the current character position and making that change directly or resuming parsing in the middle of the document.

    That would necessitate traversing the DOM and manually updating the parseInfo to include the expanded or contracted character range. The DOM is an optimal structure for traversing the nested intervals.

    Roughly the algorithm looks like this:
    (Glossing over special cases that exist depending on plugin functions.)

    # Where delta is an Integer.
    # + for character insertion
    # - for character deletion
    nudgeIntervals(domNode, delta) ->
      domNode.parseInfo.endChar += delta
      while domNode = domNode.parentNode
        domNode.parseInfo.endChar += delta
  • HTML —> DOM Mapping

    HTML to DOM mapping is not currently solved by Slowparse.

    This is a necessary problem to solve for the following capability:

    • Changing the selection selection of the HTML Editor highlights the corresponding Element in the Canvas.

    • Minimally updating the Canvas as the HTML source is edited. See “Minimal Changes”

    There are two flavors of this problem.

    1. Point: The selection is collapsed to a single point.
    2. Range: The selection covers a range of text.

    For the Point case the solution is the object in the DOM with the shortest difference between the start and end of it’s parseInfo that overlaps the character position of the selection.

    For the Range case the solution is all objects in the DOM whose parseInfo ranges partially or fully intersect the character positions in the selection.

    Note that a DOM -> HTML source mapping is a special case of Interval Tree. No intervals in the mapping between. All nested intervals are wholly contained by their parents.

  • HTML —> DOM updates

    AS edits are made to the HTML source a hidden Canvas will be updated with it’s contents.

    A recursive algorithm will compare this hidden Canvas with the Canvas used for DOM Editing.

    Only elements that have been deemed “changed” will be updated. If only an attribute has been changed/added/removed the element will not be reconstructed.

    To save speed the hidden Canvas may not be a fully ‘inflated’ DOM but a similar tree of objects. This way only objects in the DOM that must be replaced will actually be re-constructed.

    Libraries for finding diffs between DOM trees can serve as the basis for this algorithm, though changes will be required to allow for projection plugins, parseInfo updates, and the noted speed increases.

    https://github.com/pomax/DOM-diff/tree/gh-pages
    https://github.com/facebook/react

  • DOM —> HTML updates

    Updates from the DOM to the HTML should be performed through an API and not directly to the Canvas.

    This is because plugins may exist between the HTML source and the projected DOM.

    It is simpler if there is a single execution path for projection in the direction of HTML —> DOM.

    Fortunately this API can be made to mirror the existing W3C api for DOM editing. It may also be extended to a jQuery style api for convenience. This way the implementation of the DOM editor need not worry about how it’s changes will affect the source.

    A possible editor might call this:

      newChild = document.createElement('span')
    API(event.target).append newChild

    or

    API(event.target).append """
      <section class="span4">
    """

    or

    API(event.target).classList.remove 'jumbotron'

    etc.

    The API will detect and interpret the parseInfo and insert/delete specific characters in the HTML source accordingly.

    Changes through the Projector API will be treated like end-user edits and kick off the normal HTML —> DOM update procedures.

  • Editor “Chrome”

    In the course of editing it may be desireable to affix “Chrome”, or visual indications of the end-users current or potential actions .

    Because mappings between the HTML and DOM are tracked through parseInfo exapandos on DOM elements, and all edits to the DOM are sent through a Projector API, it is safe to insert elements to the Canvas DOM tree via the existing DOM editing methods. These elements will be ignored.

    The special case is when Editor “Chrome” has been inserted into an element which has been removed or so substantially changed that the diff algorithm considers the parent to have changed. Then the contents of the element will be destroyed.

  • Data Elements

    Given the following data object:

    {
      "currentPage": {
        "title":"Welcome to Example.Org"
      }
    }

    It may be desirable to transform the following source HTML

    <title>{{currentPage.title}}</title>

    into the following DOM (represented as HTML)

    <title>Welcome to Example.Org</title>
  • Repeating Elements

    A plugin might define the following behavior.

    Given source HTML:

    <ol>
      <li repeat="x in 1..3">
        List Item #{{x}}
      </li>
    </ol>

    The following DOM (represented here as HTML) will be generated:

    <ol>
      <li>List Item #1<li>
      <li>List Item #2<li>
      <li>List Item #3<li>
    </ol>

    The same plugin might define the following behavior:

    Given this source HTML

    <dl repeat="key, value of things">
      <dt>{{key}}</dt>
      <dd>{{value}}</dd>
    </dl>

    And a JavasScript Object similar to this:

    things =  {
      "Ice Cream": "Delicious",
      "Bears": "Terrifying"
    }

    The following DOM (again as HTML) is produced:

    <dl>
      <dt>Ice Cream</dt>
      <dd>Delicious</dd>
    
      <dt>Bears</dt>
      <dd>Terrifying</dd>
    </dl>
  • Transclusions

    It is common in Web Development to have a system of Layouts and Partials, the exact nomenclature differs, but many tools provide these concepts.

    Given a File: layouts/index.html

    <header>
      <img src="logo.png" alt="Example.Org" />
      <template ref="header-content" />
    </header>
    <nav>
      <template ref="sidebar-content" />
    </nav>
    <section class="container">
      <template ref="template-content" />  
    </section>

    And a file: index.html

    <template rel="layouts/index.html>
      <template id="header-content">
        <h1>Hello!</h1
      </template>
      <template id="sidebar-content">
        <a href="/about.html">Learn About Us</a>
      </template>
      <template id="template-content">
        <h1>You've reached the Index :D</h1>
        <p>That's all Folks</p>
      </template>
    </template>

    While the index.html file is opened, a plugin might project the following content in the Canvas:

    <header>
      <img src="logo.png" alt="Example.Org" />
      <h1>Hello!</h1>
    </header>
    <nav>
      <a href="/about.html">Learn About Us</a>
    </nav>
    <section class="container">
      <h1>You've reached the Index :D</h1>
      <p>That's all Folks</p>
    </section>

    Here, intersecting sections of the DOM are projected from two files.

  • Conditional Content

    Pending

{"cards":[{"_id":"355bc0185b3ecc317200001f","treeId":"355bb2785b3ecc3172000015","seq":1,"position":0.5,"parentId":null,"content":"# Hybrid HTML/DOM Editors\n \nThis document expects the reader is professionally experienced in the authoring of Web content.\n\nKnowledge of the DOM, HTML and the difference between the two are pre-requisite.\n\nThis document avoids prescribing the larger User eXperience of a Hybrid Editor, and merely (hah! *merely*) attempts to define the broad categories of editing modalities, and capabilities a Hybrid Editor provides.\n\nFurther this document attempts to define a performant and maintainable surface area upon which Hybrid Editors may be \nbuilt.\n\nWhere possible this document is descriptive rather than specific."},{"_id":"355bc2095b3ecc3172000021","treeId":"355bb2785b3ecc3172000015","seq":899455,"position":1,"parentId":"355bc0185b3ecc317200001f","content":"Authors:\n* Collin Miller"},{"_id":"355d50525b3ecc3172000039","treeId":"355bb2785b3ecc3172000015","seq":1,"position":0.625,"parentId":null,"content":"## Q & A\nDear reader. Please Ask Questions Under this Section.\n"},{"_id":"355d51665b3ecc317200003a","treeId":"355bb2785b3ecc3172000015","seq":1,"position":1,"parentId":"355d50525b3ecc3172000039","content":"**Q:** How do I Ask a Question?"},{"_id":"355d527d5b3ecc317200003b","treeId":"355bb2785b3ecc3172000015","seq":1,"position":1,"parentId":"355d51665b3ecc317200003a","content":"**A:** Ask a question by creating a new sub-item in the [Q & A item](/#q-a)\n. Hopefully somebody will answer it quickly. If you see an unanswered question and you know the answer, answer it.\n\n"},{"_id":"355c2ace5b3ecc3172000032","treeId":"355bb2785b3ecc3172000015","seq":1,"position":0.65625,"parentId":null,"content":"## Short Glossary of Terms\n"},{"_id":"355bb2965b3ecc3172000018","treeId":"355bb2785b3ecc3172000015","seq":1,"position":0.6875,"parentId":null,"content":"\n### HTML Editor\n"},{"_id":"355c08955b3ecc317200002f","treeId":"355bb2785b3ecc3172000015","seq":1,"position":1,"parentId":"355bb2965b3ecc3172000018","content":"## HTML Editors\nAn HTML Editor is a typical Text editor. Any program capable of opening a text file, allowing manipulation of it's text content, and saving the changes to the file may be used as an HTML editor.\n\nMany applications go further:\n* highlighting the tokens of HTML while the author edits\n* auto completing closing tags of html elements\n* many other nice things\n"},{"_id":"355d76a25b3ecc3172000042","treeId":"355bb2785b3ecc3172000015","seq":1,"position":0.890625,"parentId":null,"content":"### Canvas \n"},{"_id":"355d9bb25b3ecc3172000043","treeId":"355bb2785b3ecc3172000015","seq":1,"position":1,"parentId":"355d76a25b3ecc3172000042","content":"## Canvas\nThe direct or conceptual rendering of a Document Object Model to a 2d plane. A Typical Canvas is a web browser. Any subsection of the DOM may be referred to as a Canvas.\n"},{"_id":"355d713b5b3ecc317200003f","treeId":"355bb2785b3ecc3172000015","seq":1,"position":1.09375,"parentId":null,"content":"### DOM Editor\n"},{"_id":"355d74b75b3ecc3172000041","treeId":"355bb2785b3ecc3172000015","seq":1,"position":1,"parentId":"355d713b5b3ecc317200003f","content":"## DOM Editors\nA DOM Editor is a special program capable of rendering a Document Object Model Object graph to a Canvas. A DOM Editor facilitates updating the edges and nodes of that graph while re-painting the Canvas. Most Web Browsers are DOM Editors. The specification for the DOM includes an API for editing DOM graphs with methods such as:\n \n * `document.createElement(nodeName)`\n * `Node#appendChild(childNode)`\n * `document.createAttribute(attributeName)`\n * and many others...\n\nDOM Editors may go further, facilitating creation and manipulation of a DOM graph without directly using the API methods. High level modalities such as \"Drag and Drop\" may be used. Visual lists of Node types may be shown to content authors. And text may be edited directly with a keyboard. These Editors are generally known by the term: WYSIWYG, or \"What You See is What You Get\".\n"},{"_id":"355d6df35b3ecc317200003e","treeId":"355bb2785b3ecc3172000015","seq":1,"position":1.75,"parentId":null,"content":"### Code Projection"},{"_id":"355d9e6e5b3ecc3172000044","treeId":"355bb2785b3ecc3172000015","seq":1,"position":1,"parentId":"355d6df35b3ecc317200003e","content":"## Code Projection / Source Mapping\nCode projection is the direct mapping of source code from an HTML Editor to a DOM Editor.\n\nA sub-component of Code Projection is Source Mapping, or the reverse mapping of DOM Elements to character positions in the HTML Editor.\n\nThere may not be an 1-to-1 mapping of the tags written in the HTML source to the Nodes in the Canvas.\n\nIn the course of projection some elements may be transformed, expanded, or *exploded* to present alternate, extended, or generated content.\n\nThis transformation capability will be explored further in the [Plugins]( /#plugins) section.\n\nIt is ultimately the combination of Code Projection and Source Mapping that define the Hybrid Editor as a unique system. \n\nThe **Quality** of the Code Projection is of ultimate importance to the function, development, and maintainability of a Hybrid Editor."},{"_id":"355bc53a5b3ecc3172000025","treeId":"355bb2785b3ecc3172000015","seq":1,"position":2,"parentId":null,"content":"Typically tools combining HTML and DOM editing into one authoring tool have been met with negative reaction.\n\nThis is not without reason. A hybrid HTML/DOM Editor has many challenges and failure to meet these challenges leads to a sub-satisfactory work-flow.\n\n**Some of these challenges are detailed and explored:**\n"},{"_id":"355bdfc45b3ecc317200002c","treeId":"355bb2785b3ecc3172000015","seq":1,"position":3,"parentId":"355bc53a5b3ecc3172000025","content":"## Source to \"Source\" Mapping\n* Directly mapping DOM elements to HTML source locations.\n* Directly mapping HTML source locations to DOM elements.\n"},{"_id":"355c37255b3ecc3172000034","treeId":"355bb2785b3ecc3172000015","seq":1,"position":1,"parentId":"355bdfc45b3ecc317200002c","content":"### DOM —> HTML Mapping\nKnowing which character ranges in the HTML source correspond to which DOM elements in the Graph is useful for the following capabilities:\n\n* Clicking on an Element in the Canvas and moving the selection of the HTML Editor to the position in the source that defines that Element.\n\nAnd more importantly:\n\n* Knowing where to place new HTML source when changes are made to the Canvas\n\nThis problem has been solved by Mozilla in their \"Slowparse\" module: https://github.com/mozilla/slowparse\n\nContrary to the name, \"Slowparse\" is fast. Fast enough to parse a 700+ line text file on 2013 hardware in `> 10ms`. On other hardware this time may be in the `10-60ms` range. This makes Slowparse \"Fast Enough\" for typical workflows where source files can be kept under several hundred lines long. On the slower end of this scale Slowparse maybe 'debounced' to only run after user input has halted for a fraction of a second.\n\nSlow parse emits a DOM Tree in which Nodes and Attributes are given a `parseInfo` expando detailing the beginning and ending positions in the source text.\n\nFurther performance might be attained by implementing a re-entrant parser. Rather than parsing the entire document each time the source code changes, the `parseInfo` could be used to determine what part of the DOM corresponds to the current character position and making that change directly or resuming parsing in the middle of the document.\n\nThat would necessitate traversing the DOM and manually updating the `parseInfo` to include the expanded or contracted character range. The DOM is an optimal structure for traversing the nested intervals.\n\nRoughly the algorithm looks like this:\n(Glossing over special cases that exist depending on plugin functions.)\n\n```coffeescript\n# Where delta is an Integer.\n# + for character insertion\n# - for character deletion\nnudgeIntervals(domNode, delta) ->\n domNode.parseInfo.endChar += delta\n while domNode = domNode.parentNode\n domNode.parseInfo.endChar += delta\n```\n"},{"_id":"355c4c355b3ecc3172000036","treeId":"355bb2785b3ecc3172000015","seq":1,"position":2,"parentId":"355bdfc45b3ecc317200002c","content":"### HTML —> DOM Mapping\nHTML to DOM mapping is not currently solved by Slowparse.\n\nThis is a necessary problem to solve for the following capability:\n\n* Changing the selection selection of the HTML Editor highlights the corresponding Element in the Canvas.\n\n* Minimally updating the Canvas as the HTML source is edited. [See \"Minimal Changes\"](/#minimal-changes)\n\nThere are two flavors of this problem.\n\n1. Point: The selection is collapsed to a single point.\n2. Range: The selection covers a range of text.\n\nFor the Point case the solution is the object in the DOM with the shortest difference between the start and end of it's `parseInfo` that overlaps the character position of the selection.\n\nFor the Range case the solution is all objects in the DOM whose `parseInfo` ranges partially or fully intersect the character positions in the selection.\n\nNote that a DOM -> HTML source mapping is a special case of Interval Tree. No intervals in the mapping between. All nested intervals are wholly contained by their parents."},{"_id":"355be03e5b3ecc317200002d","treeId":"355bb2785b3ecc3172000015","seq":1,"position":4,"parentId":"355bc53a5b3ecc3172000025","content":"## Minimal Changes\n* Minimal changes to DOM tree when making changes to source HTML\n* Minimal changes to source HTML when making changes to DOM.\n"},{"_id":"355d688c5b3ecc317200003d","treeId":"355bb2785b3ecc3172000015","seq":899456,"position":0.5,"parentId":"355be03e5b3ecc317200002d","content":"### HTML —> DOM updates\n\nAS edits are made to the HTML source a hidden Canvas will be updated with it's contents.\n\nA recursive algorithm will compare this hidden Canvas with the Canvas used for DOM Editing.\n\nOnly elements that have been deemed \"changed\" will be updated. If only an attribute has been changed/added/removed the element will not be reconstructed.\n\nTo save speed the hidden Canvas may not be a fully 'inflated' DOM but a similar tree of objects. This way only objects in the DOM that must be replaced will actually be re-constructed.\n\nLibraries for finding diffs between DOM trees can serve as the basis for this algorithm, though changes will be required to allow for projection plugins, `parseInfo` updates, and the noted speed increases. \n\nhttps://github.com/pomax/DOM-diff/tree/gh-pages\nhttps://github.com/facebook/react"},{"_id":"355d67be5b3ecc317200003c","treeId":"355bb2785b3ecc3172000015","seq":1,"position":1,"parentId":"355be03e5b3ecc317200002d","content":"### DOM —> HTML updates\n\nUpdates from the DOM to the HTML should be performed through an API and not directly to the Canvas.\n\nThis is because plugins may exist between the HTML source and the projected DOM.\n\nIt is simpler if there is a single execution path for projection in the direction of HTML —> DOM.\n\nFortunately this API can be made to mirror the existing W3C api for DOM editing. It may also be extended to a jQuery style api for convenience. This way the implementation of the DOM editor need not worry about how it's changes will affect the source.\n\nA possible editor might call this:\n```coffeescript\n newChild = document.createElement('span')\nAPI(event.target).append newChild\n```\nor\n```coffeescripte\nAPI(event.target).append \"\"\"\n <section class=\"span4\">\n\"\"\"\n```\nor\n```coffeescript\nAPI(event.target).classList.remove 'jumbotron'\n```\netc.\n\nThe `API` will detect and interpret the `parseInfo` and insert/delete specific characters in the HTML source accordingly.\n\nChanges through the Projector API will be treated like end-user edits and kick off the normal HTML —> DOM update procedures."},{"_id":"355ec2f25b3ecc3172000058","treeId":"355bb2785b3ecc3172000015","seq":1,"position":4.5,"parentId":"355bc53a5b3ecc3172000025","content":"## Editor \"Chrome\"\n"},{"_id":"355ec34d5b3ecc3172000059","treeId":"355bb2785b3ecc3172000015","seq":1,"position":1,"parentId":"355ec2f25b3ecc3172000058","content":"### Editor \"Chrome\"\n\nIn the course of editing it may be desireable to affix \"Chrome\", or visual indications of the end-users current or potential actions .\n\nBecause mappings between the HTML and DOM are tracked through `parseInfo` exapandos on DOM elements, and all edits to the DOM are sent through a Projector API, it is safe to insert elements to the Canvas DOM tree via the existing DOM editing methods. These elements will be ignored.\n\nThe special case is when Editor \"Chrome\" has been inserted into an element which has been removed or so substantially changed that the diff algorithm considers the parent to have changed. Then the contents of the element will be destroyed."},{"_id":"355bd2785b3ecc3172000026","treeId":"355bb2785b3ecc3172000015","seq":1,"position":5,"parentId":"355bc53a5b3ecc3172000025","content":"# Plugins\nAllowing plugins to manipulate the projection between HTML and DOM.\n"},{"_id":"355dc0095b3ecc3172000047","treeId":"355bb2785b3ecc3172000015","seq":1,"position":6,"parentId":"355bc53a5b3ecc3172000025","content":" ### Data"},{"_id":"355dc80c5b3ecc317200004d","treeId":"355bb2785b3ecc3172000015","seq":1,"position":1,"parentId":"355dc0095b3ecc3172000047","content":"### Data Elements\nGiven the following data object:\n```json\n{\n \"currentPage\": {\n \"title\":\"Welcome to Example.Org\"\n }\n}\n```\n\nIt may be desirable to transform the following source HTML\n\n```html\n<title>{{currentPage.title}}</title>\n```\n\ninto the following DOM (represented as HTML)\n\n```html\n<title>Welcome to Example.Org</title>\n```"},{"_id":"355dc1875b3ecc3172000048","treeId":"355bb2785b3ecc3172000015","seq":1,"position":7,"parentId":"355bc53a5b3ecc3172000025","content":"### Repeating Elements\n"},{"_id":"355dc3375b3ecc317200004b","treeId":"355bb2785b3ecc3172000015","seq":1,"position":1,"parentId":"355dc1875b3ecc3172000048","content":"### Repeating Elements\nA plugin might define the following behavior.\n\nGiven source HTML:\n\n```html\n<ol>\n <li repeat=\"x in 1..3\">\n List Item #{{x}}\n </li>\n</ol>\n```\n\nThe following DOM (represented here as HTML) will be generated:\n\n```html\n<ol>\n <li>List Item #1<li>\n <li>List Item #2<li>\n <li>List Item #3<li>\n</ol>\n```\nThe same plugin might define the following behavior:\n\nGiven this source HTML\n```html\n<dl repeat=\"key, value of things\">\n <dt>{{key}}</dt>\n <dd>{{value}}</dd>\n</dl>\n```\nAnd a JavasScript Object similar to this:\n```javascript\nthings = {\n \"Ice Cream\": \"Delicious\",\n \"Bears\": \"Terrifying\"\n}\n```\nThe following DOM (again as HTML) is produced: \n```\n<dl>\n <dt>Ice Cream</dt>\n <dd>Delicious</dd>\n \n <dt>Bears</dt>\n <dd>Terrifying</dd>\n</dl>\n```"},{"_id":"355dc21d5b3ecc3172000049","treeId":"355bb2785b3ecc3172000015","seq":1,"position":8,"parentId":"355bc53a5b3ecc3172000025","content":"### Transclusions"},{"_id":"355dd2085b3ecc3172000051","treeId":"355bb2785b3ecc3172000015","seq":1,"position":1,"parentId":"355dc21d5b3ecc3172000049","content":"### Transclusions\nIt is common in Web Development to have a system of **Layouts** and **Partials**, the exact nomenclature differs, but many tools provide these concepts.\n\nGiven a File: `layouts/index.html`\n```html\n<header>\n <img src=\"logo.png\" alt=\"Example.Org\" />\n <template ref=\"header-content\" />\n</header>\n<nav>\n <template ref=\"sidebar-content\" />\n</nav>\n<section class=\"container\">\n <template ref=\"template-content\" /> \n</section>\n```\n\nAnd a file: `index.html`\n```html\n<template rel=\"layouts/index.html>\n <template id=\"header-content\">\n <h1>Hello!</h1\n </template>\n <template id=\"sidebar-content\">\n <a href=\"/about.html\">Learn About Us</a>\n </template>\n <template id=\"template-content\">\n <h1>You've reached the Index :D</h1>\n <p>That's all Folks</p>\n </template>\n</template>\n```\n\nWhile the `index.html` file is opened, a plugin might project the following content in the Canvas:\n\n```html\n<header>\n <img src=\"logo.png\" alt=\"Example.Org\" />\n <h1>Hello!</h1>\n</header>\n<nav>\n <a href=\"/about.html\">Learn About Us</a>\n</nav>\n<section class=\"container\">\n <h1>You've reached the Index :D</h1>\n <p>That's all Folks</p>\n</section>\n```\n\nHere, intersecting sections of the DOM are projected from two files.\n"},{"_id":"355dc8cc5b3ecc317200004e","treeId":"355bb2785b3ecc3172000015","seq":1,"position":9,"parentId":"355bc53a5b3ecc3172000025","content":"### Conditional Content"},{"_id":"355df1385b3ecc3172000052","treeId":"355bb2785b3ecc3172000015","seq":1,"position":1,"parentId":"355dc8cc5b3ecc317200004e","content":"### Conditional Content\n`Pending`"}],"tree":{"_id":"355bb2785b3ecc3172000015","name":"Hybrid DOM Editors","publicUrl":"hybrid-dom-editors"}}