hexp 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/SPEC.md DELETED
@@ -1,53 +0,0 @@
1
- # HTML Expressions (hexp) Specification
2
-
3
- HTML Expressions, hexps for short, are a subset of s-expressions. They provide a convention for working with HTML data in applications in a structured fashion.
4
-
5
- Most languages contain a DOM implementation to work with HTML/XML documents, fragments and nodes. However, generating HTML through the DOM API is verbose and tedious. A hexp implementation SHOULD implement conversions from and to DOM documents. A hexp implementation SHOULD NOT convert directly from or to HTML.
6
-
7
- A hexp implementation MUST implement hexp normalization. Several shorthands are provided for the convenience of the programmer when entering literal hexps. These non-strict hexps should be normalized to strict hexps before further manipulation.
8
-
9
- ## Strict hexps
10
-
11
- A strict hexp is a triplet, it represents a single HTML node. The first element is the tag name, the second a dictionary of attributes, the third is a list of child nodes.
12
-
13
- If the language implements the concept of a symbol (interned string), the tag name MUST BE a symbol. Otherwise it will be represented as a regular string.
14
-
15
- The attributes are represented in a dictionary (hash), with both keys and values being strings.
16
-
17
- The list of child nodes is a list (array) of other hexps or strings, the latter representing text nodes in the corresponding DOM.
18
-
19
- An example in Ruby of a strict hexp :
20
-
21
- ````ruby
22
- [:div, {'class': 'hexp-example'}, [
23
- [:p, {}, "Hello, world"]
24
- ]
25
- ]
26
- ````
27
-
28
- A normalized hexp MUST be made immutable (frozen, persistent) if the runtime supports it. Operations that alter a hexp MUST return a new hexp values, rather than changing the hexp value in-place.
29
-
30
- ## Non-strict hexps
31
-
32
- Following simplifications are allowed for entering literal hexps, the implementation MUST provide a mechanism for converting these to strict hexps.
33
-
34
- ````ruby
35
- # non-strict -> strict
36
- [:p] -> [:p, {}, []]
37
- [:p, {'class' => 'foo'}] -> [:p, {'class' => 'foo'}, []]
38
- [:p, ['hello,', [:br], 'world'] -> [:p, {}, ['hello,', [:br, {}, []], 'world']
39
- ````
40
-
41
- ### Omitting attributes or children
42
-
43
- If the dictionary of attributes is empty, it may be omitted.
44
-
45
- If the list of children is empty, it may be omitted.
46
-
47
- ### A single text node as child
48
-
49
- If the represented node its only child is a text node, a single string may be given rather than a list of children. An example would be `<p>Hello, world</p>`, this can be represented as `[:p, "Hello, world"]`, which would be normalized to `[:p, {}, ["Hello, world"]]`.
50
-
51
- ### Standard coercion protocol
52
-
53
- In a dynamically typed object-oriented language, a convention may be set for a protocol that objects can implement to return a strict hexp representation of themselves. For Ruby this will be the `to_hexp` method. In the list of children, objects can be added that implement `to_hexp`. The normalization procedure must detect that the object implements this method, and add the resulting hexps to the list of children.
data/notes DELETED
@@ -1,34 +0,0 @@
1
- http://begriffs.github.io/showpiece/
2
-
3
- TODO
4
- ====
5
- * Rename Hexp::Node to Hexp::Element
6
- * Rename Selector to Selection
7
-
8
- Issues
9
- ======
10
-
11
- Root elements should not be treated separately
12
-
13
- A `rewrite` operation currently yields all nodes except the root node. Rewrite allows you to replace a node with zero, one or more nodes. My thinking at the time was that I wanted to make sure a single Hexp was returned, so if one could rewrite the root node that would be problematic.
14
-
15
- This however makes for a special case that is not very intuitive. When implementing `Hexp::Node::Selector` I came across this again. One can use a Selector strictly as an Enumerable
16
-
17
- ```ruby
18
- # Find the first child element of all elements with class="strong"
19
- hexp.select {|el| el.class? 'strong' }.map {|el| el.children.first }
20
- ```
21
-
22
- In this case there is no reason why that shouldn't iterate the whole tree, including the node. Other operations on `Selector` however do a Rewrite of the selected elements, and in this case the "all-except-the-root-node" limitation applies.
23
-
24
- ``` ruby
25
- # Add class="strong" to all divs
26
- H[:div, [
27
- [:div, 'one'],
28
- [:div, 'two']
29
- ]
30
- ].select{|node| node.tag==:div}.attr('class', 'strong').to_hexp
31
- #=> H[:div, [H[:div, {"class"=>"strong"}, ["one"]], H[:div, {"class"=>"strong"}, ["two"]]]]
32
- ```
33
-
34
- The top-level node is unaffected. To remove this limitation `Rewriter` will have to return a `Hexp::List` when zero or multiple elements are returned. Hexp::Node and Hexp::List will also have to implement as much as possible the same interface, so they can be largely used intechangably. This should especially be possible for all select/rewrite operations.