
The WebSupport Class
********************

class class sphinx.websupport.WebSupport

   The main API class for the web support package.  All interactions
   with the web support package should occur through this class.

   The class takes the following keyword arguments:

   srcdir
      The directory containing reStructuredText source files.

   builddir
      The directory that build data and static files should be placed
      in.  This should be used when creating a "WebSupport" object
      that will be used to build data.

   datadir
      The directory that the web support data is in.  This should be
      used when creating a "WebSupport" object that will be used to
      retrieve data.

   search
      This may contain either a string (e.g. 'xapian') referencing a
      built-in search adapter to use, or an instance of a subclass of
      "BaseSearch".

   storage
      This may contain either a string representing a database uri, or
      an instance of a subclass of "StorageBackend".  If this is not
      provided, a new sqlite database will be created.

   moderation_callback
      A callable to be called when a new comment is added that is not
      displayed.  It must accept one argument: a dictionary
      representing the comment that was added.

   staticdir
      If static files are served from a location besides "'/static'",
      this should be a string with the name of that location (e.g.
      "'/static_files'").

   docroot
      If the documentation is not served from the base path of a URL,
      this should be a string specifying that path (e.g. "'docs'").


Methods
=======

WebSupport.build()

   Build the documentation. Places the data into the *outdir*
   directory. Use it like this:

      support = WebSupport(srcdir, builddir, search='xapian')
      support.build()

   This will read reStructured text files from *srcdir*. Then it will
   build the pickles and search index, placing them into *builddir*.
   It will also save node data to the database.

WebSupport.get_document(docname, username='', moderator=False)

   Load and return a document from a pickle. The document will be a
   dict object which can be used to render a template:

      support = WebSupport(datadir=datadir)
      support.get_document('index', username, moderator)

   In most cases *docname* will be taken from the request path and
   passed directly to this function. In Flask, that would be something
   like this:

      @app.route('/<path:docname>')
      def index(docname):
          username = g.user.name if g.user else ''
          moderator = g.user.moderator if g.user else False
          try:
              document = support.get_document(docname, username,
                                              moderator)
          except DocumentNotFoundError:
              abort(404)
          render_template('doc.html', document=document)

   The document dict that is returned contains the following items to
   be used during template rendering.

   * **body**: The main body of the document as HTML

   * **sidebar**: The sidebar of the document as HTML

   * **relbar**: A div containing links to related documents

   * **title**: The title of the document

   * **css**: Links to css files used by Sphinx

   * **script**: Javascript containing comment options

   This raises "DocumentNotFoundError" if a document matching
   *docname* is not found.

   Parameters:
      **docname** -- the name of the document to load.

WebSupport.get_data(node_id, username=None, moderator=False)

   Get the comments and source associated with *node_id*. If
   *username* is given vote information will be included with the
   returned comments. The default CommentBackend returns a dict with
   two keys, *source*, and *comments*. *source* is raw source of the
   node and is used as the starting point for proposals a user can
   add. *comments* is a list of dicts that represent a comment, each
   having the following items:

   +---------------+---------------------------------------------------------+
   | Key           | Contents                                                |
   +===============+=========================================================+
   | text          | The comment text.                                       |
   +---------------+---------------------------------------------------------+
   | username      | The username that was stored with the comment.          |
   +---------------+---------------------------------------------------------+
   | id            | The comment's unique identifier.                        |
   +---------------+---------------------------------------------------------+
   | rating        | The comment's current rating.                           |
   +---------------+---------------------------------------------------------+
   | age           | The time in seconds since the comment was added.        |
   +---------------+---------------------------------------------------------+
   | time          | A dict containing time information. It contains the     |
   +---------------+---------------------------------------------------------+
   | vote          | If *user_id* was given, this will be an integer         |
   +---------------+---------------------------------------------------------+
   | node          | The id of the node that the comment is attached to. If  |
   +---------------+---------------------------------------------------------+
   | parent        | The id of the comment that this comment is attached to  |
   +---------------+---------------------------------------------------------+
   | children      | A list of all children, in this format.                 |
   +---------------+---------------------------------------------------------+
   | proposal_diff | An HTML representation of the differences between the   |
   +---------------+---------------------------------------------------------+

   Parameters:
      * **node_id** -- the id of the node to get comments for.

      * **username** -- the username of the user viewing the comments.

      * **moderator** -- whether the user is a moderator.

WebSupport.add_comment(text, node_id='', parent_id='', displayed=True, username=None, time=None, proposal=None, moderator=False)

   Add a comment to a node or another comment. Returns the comment in
   the same format as "get_comments()". If the comment is being
   attached to a node, pass in the node's id (as a string) with the
   node keyword argument:

      comment = support.add_comment(text, node_id=node_id)

   If the comment is the child of another comment, provide the
   parent's id (as a string) with the parent keyword argument:

      comment = support.add_comment(text, parent_id=parent_id)

   If you would like to store a username with the comment, pass in the
   optional *username* keyword argument:

      comment = support.add_comment(text, node=node_id,
                                    username=username)

   Parameters:
      * **parent_id** -- the prefixed id of the comment's parent.

      * **text** -- the text of the comment.

      * **displayed** -- for moderation purposes

      * **username** -- the username of the user making the comment.

      * **time** -- the time the comment was created, defaults to now.

WebSupport.process_vote(comment_id, username, value)

   Process a user's vote. The web support package relies on the API
   user to perform authentication. The API user will typically receive
   a comment_id and value from a form, and then make sure the user is
   authenticated. A unique username  must be passed in, which will
   also be used to retrieve the user's past voting data. An example,
   once again in Flask:

      @app.route('/docs/process_vote', methods=['POST'])
      def process_vote():
          if g.user is None:
              abort(401)
          comment_id = request.form.get('comment_id')
          value = request.form.get('value')
          if value is None or comment_id is None:
              abort(400)
          support.process_vote(comment_id, g.user.name, value)
          return "success"

   Parameters:
      * **comment_id** -- the comment being voted on

      * **username** -- the unique username of the user voting

      * **value** -- 1 for an upvote, -1 for a downvote, 0 for an
        unvote.

WebSupport.get_search_results(q)

   Perform a search for the query *q*, and create a set of search
   results. Then render the search results as html and return a
   context dict like the one created by "get_document()":

      document = support.get_search_results(q)

   Parameters:
      **q** -- the search query
