UNPKG

diffusion

Version:

Diffusion JavaScript client

362 lines (359 loc) 11.2 kB
var parser = require('topics/topic-selector-parser'); /** * Create {@link TopicSelector} instances for use with other API methods. * <p /> * <br /> * Selectors are evaluated against topic paths. A topic path is a '/' * separated string of parts, which map to the topic hierarchy. Each part is * formed of one or more UTF characters, except '/'. Topic paths are absolute, * and evaluated from the root of the current domain. * * @example * // Create a topic selector * var selector = diffusion.selectors.parse('?foo/bar/.*'); * * @namespace diffusion.selectors */ var topicSelectors = { /** * Parse an expression to create a selector. * * This function can take any number of arguments. Each argument can be a string * or a {@link TopicSelector}. Alternatively, an array of strings and * {@link TopicSelector}s can be passed as a single argument. * * <p> * The following types of expression are supported. The type is determined * by the first character of the expression. * </p> * * <dl> * <dt>Path * <dd>Path expressions begin with the character <code>></code>. The remainder of * the expression must be a valid topic path. A topic path is a '/' * separated string of parts. Each part is formed of one or more UTF * characters, except '/'. * <p> * A {@link TopicSelector.Type#PATH PATH} selector is returned that only * selects the topic with the given path. * </p> * <h4>Abbreviated Path Expressions</h4> * <p> * In Diffusion 5.2, an alternative syntax for path expressions was added. * An <em>abbreviated path expression</em> is any valid topic path (see * above) that begins with a character other than one of <code>#</code>, * <code>?</code>, <code>></code>, <code>*</code>, <code>$</code>, * <code>%</code>, <code>&</code>, or <code><</code>. * This syntax allows most topic paths to be used directly as selector * expressions which appears more natural. * * <p> * This method converts abbreviated path expressions to standard path * expressions by prepending the <code>></code> character. Thus <code>a/b</code> is * interpreted as <code>>a/b</code>. * <p> * <code>parse("a/b").expression</code> will return <code>">a/b"</code>. * * <dt>Split-path pattern * <dd>Split-path pattern expressions begin with the character <code>?</code>. * The remainder of the expression is split into a list of regular * expressions using the <code>/</code> character as a separator. * * <p> * A {@link TopicSelector.Type.SPLIT_PATH_PATTERN SPLIT_PATH_PATTERN} * selector is returned that selects topics for which each regular * expression matches each part of the topic path at the corresponding * level. * </p> * * <dt>Full-path pattern * <dd>Full-path pattern expressions begin with the character <code>*</code>. The * remainder of the pattern is a regular expression. * * <p> * A {@link TopicSelector.Type.FULL_PATH_PATTERN FULL_PATH_PATTERN} selector * is returned that selects topics for which the regular expression matches * the complete topic path. * </p> * * <p> * Full-path patterns provide a lot of expressive power but should be used * sparingly since the server can evaluate split-path patterns more * efficiently. * * <p> * Selector sets are the preferred way to combine expressions. * <code>parse("a", "b")</code> is equivalent to the full-path expression " * <code>*[a|b]</code>", but can be evaluated more efficiently by the * server. * * <dt>Selector set * <dd>Selector set expressions begin with the character <code>#</code>. The * remainder of the expression is a list of contained selectors, formatted * as described below. * * <p> * A {@link TopicSelector.Type.SELECTOR_SET SELECTOR_SET} selector is * returned that selects topics that match any of the contained selectors. * </p> * * <p> * The contained * selectors are formatted as follows. First, any selector sets are expanded * to produce a full list of non-selector set expressions. Then the selector * expressions are concatenated, separated by the separator <code>////</code>. * This separator has been chosen as it is not valid in a path, and is not a * useful sequence in a pattern. * </p> * * </dl> * * <h2>Descendant pattern qualifiers</h2> * * <p> * Split-path and full-path pattern expressions can be further modified by * appending <code>/</code> or <code>//</code>. These control the behaviour of the * selector with respect to the descendants of the topics that match the * pattern. * * <ul> * * <li> * If the expression does not end with <code>/</code> or <code>//</code>, it selects * only the topics that match the pattern.</li> * * <li> * If the expression ends with <code>/</code>, it selects only the descendants of * the matching topics, excluding the matching topics.</li> * * <li> * If the expression ends with <code>//</code>, it selects the matching topics * and all of their descendants.</li> * </ul> * </p> * * <h2>Regular expressions</h2> * * <p> * Any {@link Pattern Java-style regular expression} can be used in * split-path and full-path patterns, with the following restrictions: * * <ul> * <li>A regular expression may not be empty. * <li>A regular expression used in split-path patterns may not contain the * path separator <code>/</code>. * <li>A regular expression used in full-path patterns may not contain the * selector set separator <code>////</code>. * </ul> * * <p> * Regular expressions that break any of these restrictions would never * match a topic path, so they make no practical difference. * </p> * * * <h2>Examples</h2> * * <h3>Path expressions</h3> * <table> * <tr> * <th></th> * <th>Matches <code>alpha/beta</code>?</th> * <th>Matches <code>alpha/beta/gamma</code>?</th> * </tr> * * <tr> * <td><code>>alpha/beta</code></td> * <td align="center">yes</td> * <td align="center">no</td> * </tr> * * <tr> * <td><code>>alpha/beta/gamma</code></td> * <td align="center">no</td> * <td align="center">yes</td> * </tr> * * <tr> * <td><code>>beta</code></td> * <td align="center">no</td> * <td align="center">no</td> * </tr> * * <tr> * <td><code>>.*</code><code>/.*</code></td> * <td align="center">no</td> * <td align="center">no</td> * </tr> * * <tr> * <td><code>>/alpha/beta/</code></td> * <td align="center">yes</td> * <td align="center">no</td> * </tr> * * </table> * * <h3>Abbreviated path expressions</h3> * <table> * <tr> * <th></th> * <th>Matches <code>alpha/beta</code>?</th> * <th>Matches <code>alpha/beta/gamma</code>?</th> * </tr> * * <tr> * <td><code>alpha/beta</code></td> * <td align="center">yes</td> * <td align="center">no</td> * </tr> * * <tr> * <td><code>alpha/beta/gamma</code></td> * <td align="center">no</td> * <td align="center">yes</td> * </tr> * * <tr> * <td><code>beta</code></td> * <td align="center">no</td> * <td align="center">no</td> * </tr> * * <tr> * <td><code>/alpha/beta/</code></td> * <td align="center">yes</td> * <td align="center">no</td> * </tr> * * </table> * * <h3>Split-path pattern expressions</h3> * <table> * <tr> * <th></th> * <th>Matches <code>alpha/beta</code>?</th> * <th>Matches <code>alpha/beta/gamma</code>?</th> * </tr> * * <tr> * <td><code>?alpha/beta</code></td> * <td align="center">yes</td> * <td align="center">no</td> * </tr> * * <tr> * <td><code>?alpha/beta/gamma</code></td> * <td align="center">no</td> * <td align="center">yes</td> * </tr> * * <tr> * <td><code>?beta</code></td> * <td align="center">no</td> * <td align="center">no</td> * </tr> * * <tr> * <td><code>?.*</code></td> * <td align="center">no</td> * <td align="center">no</td> * </tr> * * <tr> * <td><code>?.*</code><code>/.*</code></td> * <td align="center">yes</td> * <td align="center">no</td> * </tr> * * <tr> * <td><code>?alpha/beta/</code></td> * <td align="center">no</td> * <td align="center">yes</td> * </tr> * * <tr> * <td><code>?alpha/beta//</code></td> * <td align="center">yes</td> * <td align="center">yes</td> * </tr> * * <tr> * <td><code>?alpha/.*</code><code>//</code></td> * <td align="center">yes</td> * <td align="center">yes</td> * </tr> * * </table> * * <h3>Full-path pattern expressions</h3> * <table> * <tr> * <th></th> * <th>Matches <code>alpha/beta</code>?</th> * <th>Matches <code>alpha/beta/gamma</code>?</th> * </tr> * * <tr> * <td><code>*alpha/beta</code></td> * <td align="center">yes</td> * <td align="center">no</td> * </tr> * * <tr> * <td><code>*alpha/beta/gamma</code></td> * <td align="center">no</td> * <td align="center">yes</td> * </tr> * * <tr> * <td><code>*beta</code></td> * <td align="center">no</td> * <td align="center">no</td> * </tr> * * <tr> * <td><code>*.*beta</code></td> * <td align="center">yes</td> * <td align="center">no</td> * </tr> * * <tr> * <td><code>*.*</code></td> * <td align="center">yes</td> * <td align="center">yes</td> * </tr> * * * <tr> * <td><code>*alpha/beta/</code></td> * <td align="center">no</td> * <td align="center">yes</td> * </tr> * * <tr> * <td><code>*alpha/beta//</code></td> * <td align="center">yes</td> * <td align="center">yes</td> * </tr> * </table> * * @example * // Simple selector * var selector = diffusion.selectors.parse(">a/b"); * * * @example * // Creating a selector set * var selectorSet = diffusion.selectors.parse(">a", ">b"); * * @param {...String | TopicSelector | String[] } * expression - The pattern expression(s). * @return {TopicSelector} The topic selector. If multiple expressions are provided, * this will return a <code>SELECTOR_SET</code> that will match if any of the * provided <code>selectors</code> match. * @function diffusion.selectors#parse */ parse: parser }; module.exports = topicSelectors;