===========================
Using Wed in an Application
===========================
Wed is a schema-aware editor for XML documents. It runs in a web browser. The
software is at the beta stage. It is currently used in a project for editing
scholarly articles. We aim to make it extensible by means of a stable API, but
the API is likely to change quickly for now.
Make sure to read :ref:`help_browser_requirements` to learn which browsers are
supported by wed.
Known limitations:
* Wed does not load documents containing XML comments (````) or
CDATA sections.
* Wed does not load documents that include processing instructions other than
the ```` declaration at the very top of documents. (Some hold that
the XML declaration is not a processing instruction. The distinction is
irrelevant to the point being made here.)
* Wed supports most of Relax NG, with a few limitations. See the `salve
`_ package for details.
* Wed does not currently support ordering attributes according to some
preference. (The order is alphabetic.)
* Wed does not currently support multiline values in attributes.
* Empty elements appear in the editor as if they had an opening and closing tag,
irrespective of how they are encoded in the original document. So ````
and ```` are treated the same. Part of this problem is due to the
fact that wed sees the document as a DOM tree, not as a serialization. In a
DOM tree, ```` and ```` are the same.
* Elements that *must be empty* appear in the editor as if they *could* contain
contents. Note that the validator raises an error if these elements are filled
with any contents but it would be nicer if they were displayed in a way that
distinguished them from the elements that *can* be filled with contents. We
worked on a prototype that would check whether an element *can* contain
anything and display it differently if it could not. However, this required
that the rendering engine query the validating engine during rendering, which
made rendering extremely slow. Since the editor will raise an error if an
element that should be empty is filled erroneously, we've decided that a
solution to this problem can wait.
* Eventually the plan is to handle XML namespace changes completely, and there
is incipient code to deal with this; for now the safe thing to do if you have
a file using multiple namespaces is to declare them once and for all on the
top element, and never change them throughout the document. Otherwise,
problems are likely.
[A significant issue here is that the various browsers do not handle
namespaces in the same way. For instance FF and Chrome are absolutely fine if
you specify ``xmlns`` with DOM's ``setAttribute`` on an element that is on the
same namespace as the namespace specified with the new ``xmlns`` attribute and
they will produce a correct serialization. IE, on the other hand, will produce
a node with two ``xmlns`` attributes.]
* We've not tested a setup in which more than one wed instance appears on the
same page. So using more than one wed editor on the same page could be
problematic.
* Keyboard navigation in contextual menus works. However, if the mouse is
hovering over menu items, two items will be highlighted at once, which may be
confusing. This seems to be a limitation of CSS which Bootstrap does nothing
to deal with. (One element may be in the focused state (keyboard) while
another is in the hover state.)
* Wed does not work with RTL scripts. There no inherent reason wed could not
support them but the project for which it is developed currently does not need
support for RTL scripts. So no resources have been expended towards supporting
this.
* Wed is not internationalized. Although the contents of a document could be in
any language, wed's UI is in English. Again, there is no inherent reason wed
could not support other languages for the UI. The project for which it is
developed currently does not need support for other languages, hence this
state of affairs.
* See also :ref:`help_browser_requirements`.
* See also `Round-Tripping`_, as some limitations there may affect whether you
can use wed for your project.
* Wed does not use XPath nor is it currently recommended to use XPath. See
:ref:`tech_notes_xpath`.
Dependencies
============
Wed is packaged as an AMD module. To use it in a browser environment, you need
to first load RequireJS and pass to it a configuration that will allow it to
find wed's code. An example of such configuration, which allows running the
browser-dependent test suite, is located in
:github:`config/requirejs-config-dev.js`.
.. warning:: If you want to change this configuration for experimentation or to
match your local setup, please copy it to the ``local_config``
directory and edit it *there*. This directory is not tracked by
git. This is true of all files that are stored in
:github:`config/`.
Please see the :github:`package.json`, :github:`config/requirejs-config-dev.js`,
:github:`Makefile` and :github:`build.mk` files for details regarding run-time
and development dependencies. Running the test suite also requires that `saxon
`_ be installed.
Wed works with jQuery 3.x and 2.x. We strongly recommend using jQuery
3.x. jQuery 2.x is no longer maintained by its development team and thus no
longer receives security patches. There is no formal support for running wed
with jQuery 1.x or earlier versions.
The optimized builds of wed include jQuery 3.x.
Building wed's documentation **additionally** requires the following packages:
* rst2html
Running wed's selenium-based tests **additionally** requires Python 2.7 and the
Python packages listed in ``dev_requirements.txt``.
If you want to contribute to wed, your code will have to pass the checks listed
in :github:`.glerbl/repo_conf.py`. So you either have to install glerbl to get
those checks done for you or run the checks through other means. See
Contributing_.
Building
========
Everything generated during a build is output to the ``build/`` subdirectory,
except for some documentation files like ``README.html`` and ``CHANGELOG.html``,
which are in the root directory.
Wed uses gulp to build itself. You may want to create a ``gulp.local.js`` file
to record settings specific to your own build environment. Run ``gulp --help``
to see what variables you can set. Note that the variable names when use on the
command line have dashes where they would have underscore in
``gulp.local.js``. For instance, on the command line you'd use
``--behave-params`` to set the parameters passed to ``behave`` but in
``gulp.local.js`` it would be ``behave_params``. Also note that your
``gulp.local.js`` file should return a single anonymous object whose fields are
the values you want to set. For instance::
module.export = {
behave_params: "foo"
};
When everything is set, install gulp locally (``npm install gulp``) and run::
$ gulp
Gulp will install locally some packages with ``npm`` and download some external
packages that cannot be installed with ``npm`` for whatever reason and place
them in ``downloads/``. It will then create a tree of files that could be served
by a web server. The files will be in ``build/standalone/``. As the name
"standalone" implies, this build includes **everything** needed to run wed on
your own server, except the configuration for RequireJS.
Gulp will additionally create an optimized version of wed in
``build/packed/``. This is a version that has been optimized using Webpack. This
optimization exists for illustration purposes, for testing wed, and as a
possible candidate for deploying wed. See the
:ref:`tech_notes_deployment_considerations` section in :doc:`tech_notes` to
determine whether this is the optimization you want to use to deploy wed.
Testing
=======
See :doc:`tech_notes`.
Local Demos
===========
The demos, you must have a minimal server running. To run a server suitable for
the demos, you can do::
$ ./misc/server.js localhost:8888 &
The address and port ``localhost:8888`` is just a suggestion, but the link in
the documentation below assume that's the address used.
Demos Saving to a Server
------------------------
Once the server is started, point your browser to either:
* ``_ to view the demo
with the unoptimized file tree.
* or ``_ to
view the demo with an optimized file tree.
The demo currently starts with an empty document using a vanilla TEI schema. See
:doc:`help` to learn what wed can do, in general.
When you save with this demo, the data is currently dumped into a file located
at ``build/ajax/save.txt``. You won't be able to reload data from that file. For
full functionality wed needs to be used with a server able to save the data and
serve it intelligently.
:kbd:`Ctrl-\`` allows to go into development mode. Since this is meant only for
developers, you should read the source code of wed to know what this allows.
(In particular, search for ``this._development_mode`` in the
``_globalKeydownHandler`` method.)
It is possible to run the kitchen sink with a different mode than the default
one (generic) by passing a ``mode`` parameter in the URL, for instance the URL
``_ would tell the kitchen
sink to load the tei mode.
.. _label_visibility:
Label Visibility
----------------
Wed allows the user to reduce or increase the number of element labeled on the
screen. How this works is dependent in part on the specific mode that the user
has selected. For instance, the default mode that comes with wed (the "generic"
mode) knows only two levels of visibility: 0 and 1. At level 0, no elements are
labeled. At level 1, all elements are labeled. A mode with levels 0, 1, and 2
would label all elements at level 2, no elements at level 0 and some elements at
level 1. Which elements are labeled depends on how the mode designer designed
the mode.
Using
=====
Starting with version 0.31, wed is much stricter as to what it exposes to
libraries. The only parts of the code base that are safe to access are those
exported by the facade exposed as ``wed``. ``wed`` exports ``EditorInstance``
for the sake of allowing the creation of editors. However, modes **must** access
the editor through the interface defined in ``wed/mode-api`` (which is
reexported by ``wed``). It is **not** legal for a mode to cast an ``EditorAPI``
variable to anything that exposes members that are not exposed through
``wed/mode-api``. Any access that bypasses the public API is liable to break
without notice, no complaints, no recourse.
Also note that under the new regime the only module that is generally legitimate
to load is ``wed``, and nothing else. You can probably still load individual
modules from the ``standalone`` subdirectory as you used to, but this way of
operating is deprecated and will most likely be gone by version 1.0. There are a
few exceptions to the rule just given:
* You may load ``wed/onerror`` by itself to set an error handler.
* You may load ``wed/log`` by itself if you need to mess with logging.
* The files in ``wed/glue``, ``wed/patches`` and ``wed/polyfills`` can (and
sometimes *must*) be used indepdently of the main ``wed`` module.
* You may load any module from the bundled editing modes. This may be useful to
build your own modes.
To include wed in a web page you must:
* Require ``wed``
* Instantiate an ``Editor`` object of that module as follows::
var editor = wed.makeEditor(widget, options);
[...]
editor.init(data);
Between the creation of the ``Editor`` object and the call to ``init``, there
conceivably could be some calls to add event handlers or condition
handlers. The ``widget`` parameter must be an element (preferably a ``div``)
that wed will take over to install its GUI. The ``options`` parameter is
either an anonymous JavaScript object that contains the options to pass to the
editor, or it can be a ``Runtime`` object. If the latter, the options are
passed to the ``Runtime`` and the runtime is passed to the ``Editor``
instance. The ``data`` parameter is a string containing the document to edit,
in XML format.
Options
-------
The ``options`` parameter is a dictionary which at present understands the
following keys:
* ``schema``: the path to the schema to use for interpreting the document. This
file must contain the result of doing the schema conversion required by salve
since wed uses salve. See salve's documentation.
* ``mode``: a simple object recording mode parameters. This object must have a
``path`` field set to the RequireJS path of the mode. An optional ``options``
field may contain options to be passed to the mode. Wed comes bundled with a
generic mode located at :github:`lib/wed/modes/generic/generic.js`.
* ``ajaxlog``: See the documentation about :ref:`remote logging
`.
* ``save``: See the documentation about :ref:`saving `.
* ``bluejaxOptions``: This is passed directly to `Bluejax
`_ when the editor uses Bluejax. So you
can use this to configure how many times wed would retry a failing connection,
and whether it would provide error checking. The default value is::
{
tries: 3,
delay: 100,
diagnose: {
on: true,
knownServers: [
"http://www.google.com/",
"http://www.cloudfront.com/",
],
},
};
There is no ``serverURL`` set because there's no good default value for it.
Here is an example of an ``options`` object::
{
schema: 'test/tei-simplified-rng.js',
mode: {
path: 'wed/modes/generic/generic',
options: {
metadata: '.../path/to/metadata'
}
}
}
The ``mode.options`` will be passed to the generic mode when it is created. What
options are accepted and what they mean is determined by each mode.
Errors
======
The :github:`lib/wed/onerror.js` module provides an error handler that could be
used with `last-resort `_ or with any
other error handler that can call a handler that takes a single argument which
is an ``error`` DOM event. This handler tries to save the data in all editors
that exist in the window. Here is an example that uses ``last-resort``::
define(function (require) {
var lr = require("last-resort");
var onerror = require("wed/onerror");
var onError = lr.install(window);
onError.register(onerror.handler);
//...
.. warning:: **IF YOU DO NOT SET THE HANDLER TO BE CALLED ON UNCAUGHT
EXCEPTIONS, WED CANNOT DO ERROR RECOVERY.** Previous versions of
wed would automatically install a handler but the problem with this
is that it makes wed a bad player when it is used on pages that
already have their handlers.
Round-Tripping
==============
At this stage wed does not guarantee that saving an **unmodified** document will
sent the exact same string as what it was originally given to edit. This is due
to the fact that the same document can be represented in XML in multiple
ways. Notably:
* The XML declaration is not preserved.
* The order of the attributes could differ.
* The order and location of namespaces declarations could differ.
* The encoding of empty elements could differ. That is, ```` could
become ```` or vice-versa.
* Whitespace before the start tag of the top element or after the end tag of the
top element may not be preserved.
The Generic Mode
================
Wed is bundled with a single mode, the "generic" mode. We recommend to
developers who wish to create modes to use the generic mode as their
basis. Therefore, the explanations here should apply to those modes that follow
our recommendations.
The generic mode is a mode that provides almost no customization of wed's
capabilities. For instance, a custom mode could represent elements that are
paragraphs purely through indentation changes and line breaks *rather than*
start and end labels. (Such a mode does exist for the BTW project.) The generic
mode does not do this: it represents paragraphs as any other element, with a
start label and end label.
Nonetheless, the generic mode requires a minimum amount of customization in
order to be able to do its work. In particular, it needs to use a "metadata"
file that provides information on the schema being used. This is necessary
because Relax NG schemas often lack information that wed needs. For instance,
while it is possible to include documentation about the elements that are part
of a schema into a Relax NG schema, this is not the most convenient place for
it. For one thing, salve (which is what wed uses for validation) right now does
not save this information when it convert a Relax NG schema to use for
validation. Even if it did, it would not solve all problems. The TEI
documentation, for instance, is multilingual. Having it all stored in the schema
would increase its size considerably, even if the user needs using only one
language. It would be possible to produce schemas that include documentation
only in one language but then you'd need one schema per language. By having the
metadata be responsible for providing this documentation, wed can load only the
language the user needs. Another issue that the metadata addresses is the fact
that Relax NG schemas do not specify what prefix to use for namespaces. One of
the jobs of the metadata is to provide defaults for namespace prefixes. These
are used internally by the mode, rather than require mode developers to spell
out namespace URIs every time they need to refer to a namespace. The XML file
being edited can use whatever prefix desired, but the mode must have a
standardized mapping of prefix to URI.
The information provided by the metadata is not made part of the mode itself
because the information it provides may be orthogonal to the concerns of the
mode. The generic mode is a case in point: it can work just as well (or as
"generically") for editing TEI documents as DocBook documents, or documents
using any other schema. Or to take another example, TEI allows for quite a bit
of customization: elements can be redefined, added, or removed. Entire modules
can be added if a project calls for it. A mode specialized for editing TEI
documents could have its metadata load only the documentation that pertains to
the specific customization of TEI being used.
Therefore, the generic mode takes a ``metadata`` option which is a simple string
which is a path to metadata that will be loaded by the mode.
Here is an example of what the ``mode`` option passed to wed could contain::
path: 'wed/modes/generic/generic',
options: {
metadata: '../../../../../schemas/tei-math-metadata.json'
}
This tells wed to load the generic mode, and have it load the metadata file
``../../../../../schemas/tei-math-metadata.json``.
The way the generic mode operates entails that three elements must cooperate for
a file to be usable by wed:
* the correct schema must be passed to wed,
* the correct mode must be selected,
* this mode must load the correct metadata file.
Contributing
============
Contributions must pass the commit checks turned on in
:github:`.glerbl/repo_conf.py`. Use ``glerbl install`` to install the
hooks. Glerbl itself can be found at ``_. It
will eventually make its way to the Python package repository so that ``pip
install glerbl`` will work.
.. LocalWords: NG API namespace namespaces CSS RTL wed's UI github
.. LocalWords: SauceLab's OpenSauce RequireJS config requirejs dev
.. LocalWords: js jquery selectionsaverestore amd pre jsdoc rst mk
.. LocalWords: perl chai semver json Makefile saxon selenic npm
.. LocalWords: glerbl subdirectory README html CHANGELOG TEI Ctrl
.. LocalWords: RequireJS's unoptimized ajax txt tei hoc xml xsl rng
.. LocalWords: schemas init onerror CDATA versa LocalWords xmlns
.. LocalWords: multiline DOM's setAttribute ESR Attr ownerElement
.. LocalWords: globalKeydownHandler ajaxlog jQuery's teiCorpus
.. LocalWords: localhost metadata