UNPKG

stew-select

Version:

CSS selectors that allow regular expressions. Stew is a meatier soup.

857 lines (597 loc) 35.2 kB
<!DOCTYPE html> <html> <head> <title>dom-util.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <ul id="jump_to"> <li> <a class="large" href="javascript:void(0);">Jump To &hellip;</a> <a class="small" href="javascript:void(0);">+</a> <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="dom-util.html"> dom-util.coffee </a> <a class="source" href="predicate-factory.html"> predicate-factory.coffee </a> <a class="source" href="stew.html"> stew.coffee </a> </div> </li> </ul> <ul class="sections"> <li id="title"> <div class="annotation"> <h1>dom-util.coffee</h1> </div> </li> <li id="section-1"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-1">&#182;</a> </div> <p><strong>DOMUtil</strong> provides utilty functions for working with DOM trees.</p> <p>DOMUtil is designed to work with the DOM structure generated by <a href="https://github.com/tautologistics/node-htmlparser">Chris Winberry&#39;s node-htmlparser</a>. DOMUtil doesn&#39;t have a strict dependency on node-htmlparser, but it expects DOM structures compatible with those generated by node-htmlparser. See <a href="https://github.com/tautologistics/node-htmlparser#example-output">the htmlparser documentation</a> for more information about that format.</p> <p>(Currently DOMUtil should work with any DOM format that supports the <code>type</code>, <code>name</code>, <code>children</code>, <code>attribs</code> and <code>raw</code> attributes as used in htmlparser, but that may change in future verions.)</p> <p>Method names that start with <code>_</code> are subject to change without notice. Other methods may be considered a part of the public API.</p> </div> <div class="content"><div class='highlight'><pre><span class="class"><span class="keyword">class</span> <span class="title">DOMUtil</span></span></pre></div></div> </li> <li id="section-2"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-2">&#182;</a> </div> <p><strong>The DOMUtil constructor.</strong></p> <p>While the DOMUtil methods are essentially stateless (and hence thread-safe, i.e., calls to the same DOMUtil instance can be safely interleaved), DOMUtil is implemented as an instantiable class to allow for alternative configurations.</p> <p>The constuctor accepts an optional <code>params</code> map. Currently one parameter key is supported:</p> <ul> <li>The value <code>params.decode</code> (optionally) specifies a function to use when converting HTML text nodes into &quot;plain text&quot; (in the <code>to_text</code> and <code>inner_text</code> functions). This method can be used, for example, to decode HTML entities into their text equivalents. By default no conversion is made, the text nodes are output in exactly the same format as they are found in the DOM.</li> </ul> </div> <div class="content"><div class='highlight'><pre> constructor:(params = {})-&gt; <span class="property">@decode</span> = params.decode ? (str)-&gt;str</pre></div></div> </li> <li id="section-3"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-3">&#182;</a> </div> <p><strong>parse_html</strong> is a convenience function that parses a given HTML string into one or more DOM trees using the <code>htmlparser</code> library (if present). If <code>htmlparser</code> is not available, an error will be passed to the <code>callback</code> function.</p> <ul> <li><p>The <code>html</code> parameter must be a string containing one or more HTML/XML trees.</p> </li> <li><p>The <code>options</code> parameter is optional, and may contain a map of <a href="https://github.com/tautologistics/node-htmlparser/#defaulthandler-options">options to pass to htmlparser</a>.</p> </li> <li><p>The <code>callback</code> parameter should contain a function with the signature <code>callback(err,dom)</code>, where:</p> <ul> <li><p>The <code>err</code> argument will be a non-<code>null</code> value if an error occurs during the parsing.</p> </li> <li><p>Otherwise the <code>dom</code> argument will contain a single DOM object (when there is a single root tag in the given <code>html</code> string) or an array of DOM objects (when there is more than one HTML/XML structure in the given <code>html</code> string).</p> </li> </ul> </li> </ul> </div> <div class="content"><div class='highlight'><pre> parse_html:(html,options,callback)-&gt;</pre></div></div> </li> <li id="section-4"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-4">&#182;</a> </div> <p>The <code>options</code> parameter is optional, so swap <code>options</code> and <code>callback</code> if necessary.</p> </div> <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> <span class="keyword">typeof</span> options <span class="keyword">is</span> <span class="string">'function'</span> <span class="keyword">and</span> <span class="keyword">typeof</span> callback <span class="keyword">isnt</span> <span class="string">'function'</span> [ options, callback ] = [ callback, options ]</pre></div></div> </li> <li id="section-5"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-5">&#182;</a> </div> <p>If we haven&#39;t yet loaded <code>htmlparser</code>, do so now.</p> </div> <div class="content"><div class='highlight'><pre> <span class="keyword">unless</span> <span class="property">@htmlparser</span>? <span class="keyword">try</span> <span class="property">@htmlparser</span> = require <span class="string">'htmlparser'</span> <span class="keyword">catch</span> err callback(err,<span class="literal">null</span>) <span class="keyword">if</span> <span class="property">@htmlparser</span>?</pre></div></div> </li> <li id="section-6"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-6">&#182;</a> </div> <p>Now create a simple handler that invokes the given <code>callback</code>...</p> </div> <div class="content"><div class='highlight'><pre> handler = <span class="keyword">new</span> <span class="property">@htmlparser</span>.DefaultHandler (err,domset)-&gt; <span class="keyword">if</span> err? callback(err,<span class="literal">null</span>) <span class="keyword">else</span> <span class="keyword">if</span> Array.isArray(domset) <span class="keyword">and</span> domset.length &lt;= <span class="number">1</span> callback(<span class="literal">null</span>,domset[<span class="number">0</span>]) <span class="keyword">else</span> callback(<span class="literal">null</span>,domset)</pre></div></div> </li> <li id="section-7"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-7">&#182;</a> </div> <p>...create the parser...</p> </div> <div class="content"><div class='highlight'><pre> parser = <span class="keyword">new</span> <span class="property">@htmlparser</span>.Parser(handler,options)</pre></div></div> </li> <li id="section-8"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-8">&#182;</a> </div> <p>...and parse the HTML.</p> </div> <div class="content"><div class='highlight'><pre> parser.parseComplete(html)</pre></div></div> </li> <li id="section-9"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-9">&#182;</a> </div> <p><strong>as_node</strong> returns <code>nodeset[0]</code> if <code>nodeset</code> is an array, <code>nodeset</code> otherwise.</p> </div> <div class="content"><div class='highlight'><pre> as_node: (nodeset)-&gt; <span class="keyword">if</span> Array.isArray(nodeset) <span class="keyword">return</span> nodeset[<span class="number">0</span>] <span class="keyword">else</span> <span class="keyword">return</span> nodeset</pre></div></div> </li> <li id="section-10"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-10">&#182;</a> </div> <p><strong>as_nodeset</strong> returns <code>node</code> if <code>node</code> is an array, <code>[ node ]</code> otherwise.</p> </div> <div class="content"><div class='highlight'><pre> as_nodeset: (node)-&gt; <span class="keyword">if</span> Array.isArray(node) <span class="keyword">return</span> node <span class="keyword">else</span> <span class="keyword">if</span> node? <span class="keyword">return</span> [node] <span class="keyword">else</span> <span class="keyword">return</span> []</pre></div></div> </li> <li id="section-11"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-11">&#182;</a> </div> <p><strong>_kt</strong> returns <code>true</code>. It&#39;s the default filter for <code>to_text</code>.</p> </div> <div class="content"><div class='highlight'><pre> _kt: ()-&gt;<span class="literal">true</span></pre></div></div> </li> <li id="section-12"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-12">&#182;</a> </div> <p><strong>to_text</strong> returns a concatenation of all text nodes found within the given DOM <code>elt</code>.</p> <p>An optional <code>filter</code> parameter may contain a function with the signature <code>filter(node)</code> that returns <code>true</code> if the text found in or beneath the given <code>node</code> should be included in the concatenation or <code>false</code> if the text found at or below the given <code>node</code> should be excluded.</p> <p>E.g., the function:</p> <pre><code class="lang-javascript">var skip_em = function(node) { return node.name != &#39;em&#39; };</code></pre> <p>will cause <code>to_text</code> to exclude any text found within an <code>&lt;em&gt;</code> tag.</p> </div> <div class="content"><div class='highlight'><pre> to_text:(elt,filter = <span class="property">@_kt</span>)-&gt; buffer = <span class="string">''</span> <span class="property">@walk_dom</span> elt, visit:(node,node_metadata,all_metadata)=&gt;</pre></div></div> </li> <li id="section-13"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-13">&#182;</a> </div> <p>If <code>node</code> is acceptable to <code>filter</code>, then append any text, and visit its children.</p> </div> <div class="content"><div class='highlight'><pre> <span class="keyword">if</span>(filter(node,node_metadata,all_metadata)) buffer += <span class="property">@decode</span>(node.raw) <span class="keyword">if</span> node?.type <span class="keyword">is</span> <span class="string">'text'</span> <span class="keyword">and</span> node?.raw? <span class="keyword">return</span> {<span class="string">'continue'</span>:<span class="literal">true</span>,<span class="string">'visit_children'</span>:<span class="literal">true</span>} <span class="keyword">else</span></pre></div></div> </li> <li id="section-14"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-14">&#182;</a> </div> <p>If <code>node</code> is <em>not</em> acceptable to <code>filter</code>, then skip it and its children.</p> </div> <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> {<span class="string">'continue'</span>:<span class="literal">true</span>,<span class="string">'visit_children'</span>:<span class="literal">false</span>} <span class="keyword">return</span> buffer</pre></div></div> </li> <li id="section-15"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-15">&#182;</a> </div> <p><strong>inner_text</strong> is an alias for <code>to_text</code> (which see).</p> </div> <div class="content"><div class='highlight'><pre> inner_text:(elt,filter)-&gt;<span class="property">@to_text</span>(elt,filter)</pre></div></div> </li> <li id="section-16"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-16">&#182;</a> </div> <p><strong>to_html</strong> returns an HTML string representation of the given <code>elt</code> and its children (if any).</p> <p>(Currently only <code>text</code> and <code>tag</code> node types are converted, but that may change in the future.)</p> </div> <div class="content"><div class='highlight'><pre> to_html:(elt)-&gt; buffer = <span class="string">''</span> <span class="property">@walk_dom</span> elt, {</pre></div></div> </li> <li id="section-17"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-17">&#182;</a> </div> <p>When <code>visit</code>ing a node...</p> </div> <div class="content"><div class='highlight'><pre> visit:(node)-&gt; <span class="keyword">switch</span> node.type</pre></div></div> </li> <li id="section-18"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-18">&#182;</a> </div> <p>...concat the value of <code>text</code> nodes.</p> </div> <div class="content"><div class='highlight'><pre> <span class="keyword">when</span> <span class="string">'text'</span> buffer += node.raw</pre></div></div> </li> <li id="section-19"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-19">&#182;</a> </div> <p>...concat the name and attributes of <code>tag</code> nodes.</p> </div> <div class="content"><div class='highlight'><pre> <span class="keyword">when</span> <span class="string">'tag'</span> buffer += <span class="string">"&lt;<span class="subst">#{node.name}</span>"</span> <span class="keyword">if</span> node.attribs? <span class="keyword">for</span> name,value <span class="keyword">of</span> node.attribs buffer += <span class="string">" <span class="subst">#{name}</span>=\"<span class="subst">#{value}</span>\""</span> buffer += <span class="string">"&gt;"</span> <span class="keyword">return</span> <span class="literal">true</span></pre></div></div> </li> <li id="section-20"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-20">&#182;</a> </div> <p><code>after_visit</code>ing a node...</p> </div> <div class="content"><div class='highlight'><pre> after_visit:(node)-&gt; <span class="keyword">switch</span> node.type</pre></div></div> </li> <li id="section-21"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-21">&#182;</a> </div> <p>...concat the &quot;end tag&quot; for <code>tag</code> nodes.</p> </div> <div class="content"><div class='highlight'><pre> <span class="keyword">when</span> <span class="string">'tag'</span> buffer += <span class="string">"&lt;/<span class="subst">#{node.name}</span>&gt;"</span> <span class="keyword">return</span> <span class="literal">true</span> } <span class="keyword">return</span> buffer</pre></div></div> </li> <li id="section-22"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-22">&#182;</a> </div> <p><strong>inner_html</strong> returns an HTML string representation of the the children (if any) of the given <code>elt</code>.</p> <p>(Otherwise it behaves just like <code>to_html</code>, which see.)</p> </div> <div class="content"><div class='highlight'><pre> inner_html:(elt)-&gt; buffer = <span class="literal">null</span></pre></div></div> </li> <li id="section-23"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-23">&#182;</a> </div> <p>If <code>elt</code> is an array, invoke <code>to_html</code> on the children of each element of in the array.</p> </div> <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> Array.isArray(elt) buffer = <span class="string">''</span> <span class="keyword">for</span> node <span class="keyword">in</span> elt <span class="keyword">if</span> node.children? buffer += <span class="property">@to_html</span>(node.children)</pre></div></div> </li> <li id="section-24"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-24">&#182;</a> </div> <p>Otherwise <code>to_html</code> on the childen of <code>elt</code>.</p> </div> <div class="content"><div class='highlight'><pre> <span class="keyword">else</span> <span class="keyword">if</span> elt?.children? buffer = <span class="property">@to_html</span> elt.children <span class="keyword">return</span> buffer</pre></div></div> </li> <li id="section-25"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-25">&#182;</a> </div> <p><strong>walk_dom</strong> performs a depth-first walk of the given DOM tree (or trees), invoking a specified &quot;visit&quot; function for each node.</p> <ul> <li><p>The <code>dom</code> parameter is either a single DOM node or an array of DOM nodes.</p> </li> <li><p>The <code>callbacks</code> parameter is a map that contains (at minimum) an attribute named <code>visit</code> containing a function with the signature:</p> <pre><code>visit(node,node_metadata,all_metadata)</code></pre> <p> where:</p> <ul> <li><code>node</code> is the DOM node currently being visited,</li> <li><code>node_metadata</code> is a map containing <code>parent</code>, <code>path</code>, <code>siblings</code> and <code>sib_index</code> keys, and</li> <li><code>all_metadata</code> is an array of <code>node_metadata</code> values for each previously visited nodes, indexed by the value stored at <code>node._stew_node_id</code>.</li> </ul> </li> <li><p>The <code>callbacks.visit</code> function should return a map containing <code>continue</code> and <code>visit-children</code> attributes.</p> <ul> <li><p>When <code>visit-children</code> is <code>true</code>, the children of <code>node</code> (if any) will be visited next. When <code>false</code>, the <code>node</code>&#39;s children will be skipped, but processing will continue with <code>node</code>&#39;s siblings (or <code>node</code>&#39;s parent&#39;s, siblings, etc.)</p> </li> <li><p>When <code>continue</code> is <code>false</code>, all subsequent processing will be aborted and the <code>walk_dom</code> method will exit as soon as possible.</p> </li> <li><p>If the value returned by <code>visit</code> is a boolean, that value will be used for both <code>continue</code> and <code>visit-children</code>.</p> </li> </ul> </li> <li><p>If <code>callbacks</code> is a function (rather than a map) it be used as the <code>visit</code> function.</p> </li> </ul> </div> <div class="content"><div class='highlight'><pre> walk_dom:(dom,callbacks)-&gt;</pre></div></div> </li> <li id="section-26"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-26">&#182;</a> </div> <p>Fiddle with the input parameters if needed.</p> </div> <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> <span class="keyword">typeof</span> callbacks <span class="keyword">is</span> <span class="string">'function'</span> callbacks = { visit:callbacks } nodes = <span class="property">@as_nodeset</span>(dom)</pre></div></div> </li> <li id="section-27"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-27">&#182;</a> </div> <p>Create a container for all the node metadata.</p> </div> <div class="content"><div class='highlight'><pre> dom_metadata = [] <span class="keyword">for</span> node, sib_index <span class="keyword">in</span> nodes</pre></div></div> </li> <li id="section-28"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-28">&#182;</a> </div> <p>Create the metadata for this node...</p> </div> <div class="content"><div class='highlight'><pre> node_metadata = { parent:<span class="literal">null</span>, path:[], siblings:nodes, sib_index: sib_index } node._stew_node_id = dom_metadata.length</pre></div></div> </li> <li id="section-29"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-29">&#182;</a> </div> <p>...add it to the container...</p> </div> <div class="content"><div class='highlight'><pre> dom_metadata.push node_metadata</pre></div></div> </li> <li id="section-30"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-30">&#182;</a> </div> <p>...visit the node...</p> </div> <div class="content"><div class='highlight'><pre> should_continue = <span class="property">@_unguarded_walk_dom</span>(node,node_metadata,dom_metadata,callbacks)</pre></div></div> </li> <li id="section-31"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-31">&#182;</a> </div> <p>...and exit if needed.</p> </div> <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> <span class="keyword">not</span> should_continue <span class="keyword">break</span></pre></div></div> </li> <li id="section-32"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-32">&#182;</a> </div> <p><strong>_unguarded_walk_dom</strong> is the &quot;inner&quot; implementation of <code>walk_dom</code>. See <code>walk_dom</code> for more information</p> <ul> <li><code>node</code> is the current DOM node to visit.</li> <li><code>node_metadata</code> is a map containing:<ul> <li><code>parent</code> - the parent of this node, if any</li> <li><code>path</code> - an array of this node&#39;s ancestors (from &quot;root&quot; to parent)</li> <li><code>siblings</code> - an array of this node&#39;s parent&#39;s children</li> <li><code>sib_index</code> - the index of this node in the <code>siblings</code> array</li> </ul> </li> <li><code>dom_metadata</code> is an array of <code>node_metadata</code> objects, indexed by <code>node._stew_node_id</code>. Only the already visited nodes are contained in this array.</li> <li><code>callbacks</code> is the map of callbacks passed to <code>walk_dom</code>, which see.</li> </ul> <p><code>_unguarded_walk_dom</code> will return <code>true</code> if processing should continue (typically with <code>node</code>&#39;s next sibling), or <code>false</code> if processing is complete an no more nodes should be visited.</p> </div> <div class="content"><div class='highlight'><pre> _unguarded_walk_dom:(node,node_metadata,dom_metadata,callbacks)-&gt;</pre></div></div> </li> <li id="section-33"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-33">&#182;</a> </div> <p>Visit the current node.</p> </div> <div class="content"><div class='highlight'><pre> response = {<span class="string">'continue'</span>:<span class="literal">true</span>,<span class="string">'visit_children'</span>:<span class="literal">true</span>} <span class="keyword">if</span> callbacks.visit? response = callbacks.visit(node,node_metadata,dom_metadata)</pre></div></div> </li> <li id="section-34"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-34">&#182;</a> </div> <p>If processing should continue...</p> </div> <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> response <span class="keyword">is</span> <span class="literal">true</span> <span class="keyword">or</span> response?[<span class="string">'continue'</span>] <span class="keyword">is</span> <span class="literal">true</span> <span class="keyword">or</span> (<span class="keyword">not</span> response?[<span class="string">'continue'</span>]?)</pre></div></div> </li> <li id="section-35"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-35">&#182;</a> </div> <p>...and this node&#39;s children should be processed...</p> </div> <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> node.children? <span class="keyword">and</span> (response <span class="keyword">is</span> <span class="literal">true</span> <span class="keyword">or</span> response?[<span class="string">'visit_children'</span>] <span class="keyword">is</span> <span class="literal">true</span> <span class="keyword">or</span> (<span class="keyword">not</span> response?[<span class="string">'visit_children'</span>]?))</pre></div></div> </li> <li id="section-36"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-36">&#182;</a> </div> <p>...create the <code>path</code> to this <code>node</code>&#39;s children...</p> </div> <div class="content"><div class='highlight'><pre> new_path = [].concat(node_metadata.path) new_path.push(node)</pre></div></div> </li> <li id="section-37"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-37">&#182;</a> </div> <p>...and recursively visit each child in turn...</p> </div> <div class="content"><div class='highlight'><pre> <span class="keyword">for</span> child,index <span class="keyword">in</span> node.children new_node_metadata = { parent:node, path:new_path, siblings:node.children, sib_index: index } child._stew_node_id = dom_metadata.length dom_metadata.push new_node_metadata should_continue = <span class="property">@_unguarded_walk_dom</span>(child,new_node_metadata,dom_metadata,callbacks)</pre></div></div> </li> <li id="section-38"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-38">&#182;</a> </div> <p>...aborting further processing if needed.</p> </div> <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> <span class="keyword">not</span> should_continue <span class="keyword">return</span> <span class="literal">false</span></pre></div></div> </li> <li id="section-39"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-39">&#182;</a> </div> <p>...invoke the post-visit callback, if any...</p> </div> <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> callbacks[<span class="string">'after_visit'</span>]? response = callbacks.after_visit(node,node_metadata,dom_metadata)</pre></div></div> </li> <li id="section-40"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-40">&#182;</a> </div> <p>...aborting further processing if needed.</p> </div> <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> response <span class="keyword">is</span> <span class="literal">true</span> <span class="keyword">or</span> response?[<span class="string">'continue'</span>] <span class="keyword">is</span> <span class="literal">true</span> <span class="keyword">or</span> (<span class="keyword">not</span> response?[<span class="string">'continue'</span>]?) <span class="keyword">else</span> <span class="comment"># no `after_visit` callback</span> <span class="keyword">return</span> <span class="literal">true</span> <span class="keyword">else</span> <span class="comment"># processing should not continue</span> <span class="keyword">return</span> <span class="literal">false</span></pre></div></div> </li> <li id="section-41"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-41">&#182;</a> </div> <p>The DOMUtil class is exported under the name <code>DOMUtil</code>.</p> </div> <div class="content"><div class='highlight'><pre>exports = exports ? <span class="keyword">this</span> exports.DOMUtil = DOMUtil</pre></div></div> </li> </ul> </div> </body> </html>