Skip to content
Browse files

updated bespin

  • Loading branch information...
1 parent 7d99757 commit 6743e3858868217739c9775584cfcddf79ada89d @matthewfl committed Jan 4, 2011
Showing with 16,657 additions and 3,452 deletions.
  1. BIN Bespin/BespinEmbedded/compressors/compiler.jar
  2. +16 −3 Bespin/BespinEmbedded/docs/devguide/index.html
  3. +1 −0 Bespin/BespinEmbedded/docs/embedding/appconfig.html
  4. +6 −6 Bespin/BespinEmbedded/docs/embedding/building.html
  5. +4 −0 Bespin/BespinEmbedded/docs/embedding/index.html
  6. +168 −0 Bespin/BespinEmbedded/docs/embedding/installing.html
  7. +14 −8 Bespin/BespinEmbedded/docs/index.html
  8. +79 −18 Bespin/BespinEmbedded/docs/pluginguide/template.html
  9. +9 −0 Bespin/BespinEmbedded/docs/releases/notes09.html
  10. BIN Bespin/BespinEmbedded/docs/tutorials/ToolbarAsList.png
  11. +530 −0 Bespin/BespinEmbedded/docs/tutorials/commands.html
  12. +510 −0 Bespin/BespinEmbedded/docs/tutorials/gui.html
  13. +465 −0 Bespin/BespinEmbedded/docs/tutorials/gui.html.markdown.orig
  14. +108 −0 Bespin/BespinEmbedded/docs/tutorials/index.html
  15. +20 −43 Bespin/BespinEmbedded/lib/dryice/boot.js
  16. +79 −12 Bespin/BespinEmbedded/lib/dryice/samples/programmatic.html
  17. +1 −1 Bespin/BespinEmbedded/lib/dryice/samples/sample.html
  18. +1 −2 Bespin/BespinEmbedded/lib/tiki.js
  19. +1 −1 Bespin/BespinEmbedded/plugins/boot/bespin/console.js
  20. +20 −1 Bespin/BespinEmbedded/plugins/boot/bespin/promise.js
  21. +3 −1 Bespin/BespinEmbedded/plugins/boot/bespin/util/util.js
  22. +604 −0 Bespin/BespinEmbedded/plugins/labs/collab/index.js
  23. +1,508 −0 Bespin/BespinEmbedded/plugins/labs/collab/mobwrite/core.js
  24. +277 −0 Bespin/BespinEmbedded/plugins/labs/collab/package.json
  25. +82 −0 Bespin/BespinEmbedded/plugins/labs/collab/resources/social.css
  26. +611 −0 Bespin/BespinEmbedded/plugins/labs/collab/social.js
  27. +10 −0 Bespin/BespinEmbedded/plugins/labs/collab/templates/followers.htmlt
  28. +10 −0 Bespin/BespinEmbedded/plugins/labs/collab/templates/groups.htmlt
  29. +10 −0 Bespin/BespinEmbedded/plugins/labs/collab/templates/members.htmlt
  30. +21 −0 Bespin/BespinEmbedded/plugins/labs/collab/templates/shares.htmlt
  31. +158 −0 Bespin/BespinEmbedded/plugins/labs/collab/user.js
  32. +73 −0 Bespin/BespinEmbedded/plugins/labs/collab/util.js
  33. +308 −0 Bespin/BespinEmbedded/plugins/labs/collab/view.js
  34. +56 −30 Bespin/BespinEmbedded/plugins/supported/appconfig/index.js
  35. +2 −1 Bespin/BespinEmbedded/plugins/supported/appconfig/package.json
  36. +1 −1 Bespin/BespinEmbedded/plugins/supported/bespin_server/commands.js
  37. +0 −6 Bespin/BespinEmbedded/plugins/supported/bespin_server/package.json
  38. +1 −0 Bespin/BespinEmbedded/plugins/supported/canon/history.js
  39. +0 −5 Bespin/BespinEmbedded/plugins/supported/command_line/package.json
  40. +3 −3 Bespin/BespinEmbedded/plugins/supported/command_line/templates/cli.htmlt
  41. +65 −0 Bespin/BespinEmbedded/plugins/supported/diff_syntax.js
  42. +36 −10 Bespin/BespinEmbedded/plugins/supported/file_commands/index.js
  43. +5 −0 Bespin/BespinEmbedded/plugins/supported/file_commands/package.json
  44. +52 −2 Bespin/BespinEmbedded/plugins/supported/js_syntax.js
  45. +138 −0 Bespin/BespinEmbedded/plugins/supported/jslint_command.js
  46. +109 −93 Bespin/BespinEmbedded/plugins/supported/matcher/index.js
  47. +0 −6 Bespin/BespinEmbedded/plugins/supported/settings/package.json
  48. +10 −2 Bespin/BespinEmbedded/plugins/supported/standard_syntax.js
  49. +1 −0 Bespin/BespinEmbedded/plugins/supported/syntax_directory.js
  50. +7 −0 Bespin/BespinEmbedded/plugins/supported/syntax_manager/index.js
  51. +1 −0 Bespin/BespinEmbedded/plugins/supported/syntax_manager/package.json
  52. +13 −0 Bespin/BespinEmbedded/plugins/supported/syntax_worker.js
  53. +77 −72 Bespin/BespinEmbedded/plugins/supported/templater.js
  54. +1 −2 Bespin/BespinEmbedded/plugins/supported/text_editor/models/buffer.js
  55. +33 −14 Bespin/BespinEmbedded/plugins/supported/text_editor/package.json
  56. +5 −4 Bespin/BespinEmbedded/plugins/supported/text_editor/views/canvas.js
  57. +2 −1 Bespin/BespinEmbedded/plugins/supported/text_editor/views/editor.js
  58. +90 −14 Bespin/BespinEmbedded/plugins/supported/text_editor/views/gutter.js
  59. +31 −12 Bespin/BespinEmbedded/plugins/supported/text_editor/views/text.js
  60. +30 −16 Bespin/BespinEmbedded/plugins/supported/text_editor/views/textinput.js
  61. +70 −0 Bespin/BespinEmbedded/plugins/supported/toolbar/index.js
  62. +71 −0 Bespin/BespinEmbedded/plugins/supported/toolbar/items.js
  63. +56 −0 Bespin/BespinEmbedded/plugins/supported/toolbar/package.json
  64. BIN Bespin/BespinEmbedded/plugins/supported/toolbar/resources/logo.png
  65. +59 −0 Bespin/BespinEmbedded/plugins/supported/toolbar/resources/toolbar.less
  66. +13 −6 Bespin/BespinEmbedded/plugins/supported/userident/index.js
  67. +0 −6 Bespin/BespinEmbedded/plugins/supported/userident/package.json
  68. +1 −1 Bespin/BespinEmbedded/plugins/supported/userident/templates/login.htmlt
  69. +10 −2 Bespin/BespinEmbedded/plugins/supported/whitetheme/index.js
  70. +231 −0 Bespin/BespinEmbedded/plugins/supported/whitetheme/index.js.orig
  71. +0 −5 Bespin/BespinEmbedded/plugins/thirdparty/diff.js
  72. +9 −2 Bespin/BespinEmbedded/plugins/thirdparty/gritter/package.json
  73. 0 ...in/BespinEmbedded/plugins/thirdparty/gritter/resources/{jquery.gritter.css → jquery.gritter.less}
  74. +5,675 −0 Bespin/BespinEmbedded/plugins/thirdparty/jslint.js
  75. +169 −83 Bespin/BespinEmbedded/plugins/thirdparty/traits.js
  76. +158 −137 Bespin/BespinEmbedded/prebuilt/BespinEmbedded.js
  77. +2,215 −1,109 Bespin/BespinEmbedded/prebuilt/BespinEmbedded.uncompressed.js
  78. +449 −457 Bespin/BespinEmbedded/prebuilt/BespinMain.js
  79. +581 −1,221 Bespin/BespinEmbedded/prebuilt/BespinMain.uncompressed.js
  80. +13 −12 Bespin/BespinEmbedded/prebuilt/BespinWorker.js
  81. +77 −6 Bespin/BespinEmbedded/prebuilt/BespinWorker.uncompressed.js
  82. +51 −0 Bespin/BespinEmbedded/prebuilt/resources/whitetheme/theme.less
  83. +79 −12 Bespin/BespinEmbedded/prebuilt/samples/programmatic.html
  84. +1 −1 Bespin/BespinEmbedded/prebuilt/samples/sample.html
  85. +1 −1 Bespin/BespinEmbedded/sample.json
  86. +191 −0 Bespin/coffeescript_syntax.js
  87. +1 −1 Bespin/settings.json
View
BIN Bespin/BespinEmbedded/compressors/compiler.jar
Binary file not shown.
View
19 Bespin/BespinEmbedded/docs/devguide/index.html
@@ -93,9 +93,22 @@ <h2 id="web-subtitle">Getting Started</h2>
<p>paver start</p>
<p>This will start the Bespin server. You can now access the Bespin editor at http://localhost:8080/ in you browser.</p>
<p>Have fun!</p>
-<h2>Contributing to Bespin</h2>
-<p>For details see:
-:[[Labs/Bespin/Contributing]]</p>
+<h2>Coding Conventions</h2>
+<p>JavaScript code should follow the <a href="http://javascript.crockford.com/code.html">Crockford Code Conventions</a>. With a few minor modifications:</p>
+<ul>
+<li>
+<p>Namespaces: Crockford does not mention namespaces, probably because owning the global namespace allows you to use as much as you want. Our code is likely to be used in many different places so we should not pollute the global namespace needlessly. Our code is organized in [http://commonjs.org/specs/modules/1.0.html CommonJS] modules, so every variable should either be a "var" or attached to the "exports" object.</p>
+</li>
+<li>
+<p>_private: We agree that prefixing variables with an underscore provides no actual protection, however we think of it as a warning. "Use of this member is unsupported and likely to break without warning in future revisions". In early versions of Bespin where we are experimenting a lot, allowing 3rd parties to join in the experiment is valuable. As Bespin becomes more stable and finalized, we might expect underscored members to be replaced with closure scoped variables.</p>
+</li>
+<li>
+<p>Documentation: Bespin JavaScript is documented with <a href="http://code.google.com/p/jsdoc-toolkit/w/list">JSDoc</a>, which in practice means prefixing functions with a set of comments that use various tags.</p>
+</li>
+<li>
+<p>var first: The standard recommends putting var statements as the first statements in the function body. Crockford doesn't always follow this advice and we reserve the right to follow this lead ;-)</p>
+</li>
+</ul>
</div>
<!-- / MAIN COLUMN -->
View
1 Bespin/BespinEmbedded/docs/embedding/appconfig.html
@@ -154,6 +154,7 @@ <h2 class="compact">Contents</h2>
<li><a href="index.html">Introduction</a></li>
<li><a href="building.html">Creating a Custom, Embedded Bespin</a></li>
<li><a href="appconfig.html">Application Configuration</a></li>
+<li><a href="installing.html">Installing Plugins</a></li>
</ul>
View
12 Bespin/BespinEmbedded/docs/embedding/building.html
@@ -164,13 +164,12 @@ <h2 id="web-subtitle">Building</h2>
<p>Run "dryice -h" for up-to-date usage information.</p>
<p>Generally speaking, using dryice is just a matter of pointing the tool at
your manifest file, which describes what needs to be built.</p>
-<p>After the JavaScript and CSS are generated, you will likely want to compress
+<p>After the JavaScript files are generated, you will likely want to compress
those files for faster loading over the internet. dryice can do this for
-you, using the Closure Compiler for the JavaScript and YUI Compressor for
-the CSS. These are both included in the Customizable package in the
-"compressors" directory. To activate dryice compression, run a command like
-this one:</p>
-<div class="codehilite"><pre><span class="n">dryice</span> <span class="o">-</span><span class="n">j</span> <span class="n">compressors</span><span class="sr">/compiler.jar -c compressors/</span><span class="n">yuicompressor</span><span class="o">.</span><span class="n">jar</span> <span class="n">MANIFEST</span><span class="o">.</span><span class="n">JSON</span>
+you, using the Closure Compiler for the JavaScript. Thise is included in the
+in the "compressors" directory. To activate dryice compression, run a
+command like this one:</p>
+<div class="codehilite"><pre><span class="n">dryice</span> <span class="o">-</span><span class="n">j</span> <span class="n">compressors</span><span class="o">/</span><span class="n">compiler</span><span class="o">.</span><span class="n">jar</span> <span class="n">MANIFEST</span><span class="o">.</span><span class="n">JSON</span>
</pre></div>
@@ -199,6 +198,7 @@ <h2 class="compact">Contents</h2>
<li><a href="index.html">Introduction</a></li>
<li><a href="building.html">Creating a Custom, Embedded Bespin</a></li>
<li><a href="appconfig.html">Application Configuration</a></li>
+<li><a href="installing.html">Installing Plugins</a></li>
</ul>
View
4 Bespin/BespinEmbedded/docs/embedding/index.html
@@ -167,6 +167,9 @@ <h2 id="web-subtitle">Introduction</h2>
<p>Where <code>env</code> is the environment variable of the Bespin that container's size changed.</p>
+<h1>Embedding Bespin in XULRunner</h1>
+<p>Bespin's use of web workers and other features requires it to be loaded via
+resource:// urls if used in XULRunner iframes.</p>
</div>
<!-- / MAIN COLUMN -->
@@ -183,6 +186,7 @@ <h2 class="compact">Contents</h2>
<li><a href="index.html">Introduction</a></li>
<li><a href="building.html">Creating a Custom, Embedded Bespin</a></li>
<li><a href="appconfig.html">Application Configuration</a></li>
+<li><a href="installing.html">Installing Plugins</a></li>
</ul>
View
168 Bespin/BespinEmbedded/docs/embedding/installing.html
@@ -0,0 +1,168 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8">
+
+ <title>Bespin Embedded Guide</title>
+
+ <link rel="stylesheet" type="text/css" href="../css/reset.css">
+ <link rel="stylesheet" type="text/css" href="../css/stylesheet.css" media="screen,projection">
+ <link rel="stylesheet" type="text/css" href="../css/colorful.css">
+</head>
+<body>
+
+<!-- MAIN CONTAINER -->
+<div id="main-container">
+
+<!-- MENU -->
+<ul id="menu">
+ <li><a href="../index.html" title="Home">Home</a></li>
+ <li><a href="../userguide/index.html" title="User Guide">Using Bespin</a></li>
+ <li><a href="../pluginguide/index.html" title="Plugin Guide">Creating Plugins</a></li>
+ <li class="current"><a href="../embedding/index.html" title="Embedding Bespin in your app">Embedding</a></li>
+ <li><a href="../devguide/index.html" title="Developer's Guide">Developing Bespin</a></li>
+</ul>
+<!-- / MENU -->
+
+<h1 id="web-title">Bespin Embedded Guide</h1>
+<h2 id="web-subtitle">Installing Plugins</h2>
+
+<!-- INDEX PAGE -->
+
+<!-- MAIN COLUMN -->
+<div id="maincol">
+<h2>Plugin Formats</h2>
+<p>When you download a plugin, you're likely to get one of three kinds of files:</p>
+<ul>
+<li>.js</li>
+<li>.zip</li>
+<li>.tar.gz (or .tgz)</li>
+</ul>
+<p>Bespin can directly work with the <code>.js</code> files. The other two formats are
+archive formats that contain multiple files and directories. You will need
+to expand those archives into your plugin directory (see "Where To Put
+The Files" below).</p>
+<h2>Where To Put The Files</h2>
+<p>In the <a href="building.html">building</a> section of this guide, we described the
+manifest file. The manifest file allows you to set a <code>search_path</code> option
+that dryice will use when building Bespin.</p>
+<p>We recommend a directory structure that is something like this:</p>
+<ul>
+<li>your_project (top level directory with everything you need)<ul>
+<li>bespin (the original Bespin Embedded files provided by the Bespin project)</li>
+<li>plugins (your custom-created plugins)</li>
+<li>thirdparty (plugins that you've downloaded from elsewhere)</li>
+</ul>
+</li>
+</ul>
+<p>With this kind of directory structure, you can upgrade Bespin at will just by
+deleting the <code>bespin</code> directory and putting a new one in its place. In your
+manifest file, you'll add both <code>plugins</code> and <code>thirdparty</code> to your <code>search_path</code>.</p>
+<p>So, when you download a plugin, you'll either drop the <code>.js</code> file into the
+<code>thirdparty</code> directory, or you'll expand the <code>.zip</code> or <code>.tar.gz</code> file into
+the thirdparty directory. Expanding the <code>.zip</code> or <code>.tar.gz</code> file should create
+a new directory that has a file called <code>package.json</code> in it. The name of the
+plugin is the name of the directory.</p>
+<p>A complete example:</p>
+<ul>
+<li>your_project<ul>
+<li>bespin</li>
+<li>plugins<ul>
+<li>mygroovyplugin.js</li>
+</ul>
+</li>
+<li>thirdparty<ul>
+<li>markdown.js</li>
+<li>toolbar<ul>
+<li>package.json</li>
+<li>index.js</li>
+<li>resources<ul>
+<li>icon1.png</li>
+<li>icon2.png</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+<p>In this example, we have downloaded two plugins created by other people:
+<code>markdown</code> and <code>toolbar</code>. The <code>markdown</code> plugin is contained in a single <code>.js</code>
+file that we've placed in the <code>thirdparty</code> directory. The <code>toolbar</code> plugin
+may have started out as a <code>.zip</code> file, and we've expanded it out to create
+a directory called <code>toolbar</code> with a <code>package.json</code> file in it.</p>
+</div>
+<!-- / MAIN COLUMN -->
+
+<!-- SIDEBAR -->
+<div id="sidebar">
+
+
+
+
+
+
+<h2 class="compact">Contents</h2>
+<ul class="compact">
+<li><a href="index.html">Introduction</a></li>
+<li><a href="building.html">Creating a Custom, Embedded Bespin</a></li>
+<li><a href="appconfig.html">Application Configuration</a></li>
+<li><a href="installing.html">Installing Plugins</a></li>
+</ul>
+
+
+
+
+
+</div>
+<!-- / SIDEBAR -->
+
+<!-- / MAIN CONTAINER -->
+</div>
+
+<!-- FOOTER -->
+<div id="footer">
+ <!-- COLUMN ONE -->
+ <div>
+ <h2 class="compact">Useful Links</h2>
+ <ul class="compact">
+ <li><a href="http://mozillalabs.com/bespin/">Bespin project home page</a></li>
+ <li><a href="https://wiki.mozilla.org/Labs/Bespin">Wiki</a></li>
+ </ul>
+ </div>
+ <!-- / COLUMN ONE -->
+
+ <!-- COLUMN TWO -->
+ <div>
+ <h2 class="compact">Developer Resources</h2>
+ <ul class="compact">
+ <li><a href="http://hg.mozilla.org/labs/bespinclient/">Main Code Repository</a></li>
+ <li><a href="http://hg.mozilla.org/labs/bespinserver/">Python server repository</a></li>
+ <li><a href="http://groups.google.com/group/bespin-core/">bespin-core mailing list for developers</a></li>
+ <li><a href="http://groups.google.com/group/bespin-commits/">bespin-commits mailing list for repository commit messages</a></li>
+ <li><a href="https://bugzilla.mozilla.org/buglist.cgi?product=bespin">Bug List</a></li>
+ </ul>
+ </div>
+ <!-- / COLUMN TWO -->
+
+ <!-- COLUMN THREE -->
+ <div>
+ <h2 class="compact">Get Help</h2>
+ <ul class="compact">
+ <li>The <a href="http://groups.google.com/group/bespin/">Bespin mailing list</a></li>
+ <li>Via IRC: <a href="irc://irc.mozilla.org/bespin">#bespin on irc.mozilla.org</a></li>
+ </ul>
+
+ <h2 class="compact">Documentation Template</h2>
+ <ul class="compact">
+ <li>Adapted from a design by <a href="http://www.mgrabovsky.is-game.com/">Matěj Grabovský</a></li>
+ </ul>
+ </div>
+ <!-- / COLUMN THREE -->
+</div>
+<!-- / FOOTER -->
+
+</body>
+</html>
View
22 Bespin/BespinEmbedded/docs/index.html
@@ -34,11 +34,17 @@ <h2 id="web-subtitle">Using and Extending Bespin</h2>
<p><a href="glossary.html">The Glossary</a> will clear up any questions you have about terminology used on the project.</p>
<p>Find out what's new, in the
<a href="releases/notes09.html">Bespin 0.9 Release Notes</a>.</p>
-<h2>User's Guide</h2>
+<h2>Embedder's Guide</h2>
<ul>
-<li><em>Important</em> <a href="userguide/server_roadmap.html">Bespin Server Roadmap</a></li>
-<li><a href="userguide/index.html">Introduction</a></li>
-<li><a href="userguide/vcs.html">Version Control Systems</a></li>
+<li><a href="embedding/index.html">Introduction</a></li>
+<li><a href="embedding/building.html">Creating a custom, embedded Bespin</a></li>
+<li><a href="embedding/appconfig.html">Application Configuration (Gluing Bespin Together)</a></li>
+<li><a href="embedding/installing.html">Installing Plugins</a></li>
+</ul>
+<h2>Tutorials</h2>
+<ul>
+<li><a href="tutorials/commands.html">Manipulating Text through Commands</a></li>
+<li><a href="tutorials/gui.html">Adding to the GUI</a></li>
</ul>
<h2>Plugin Author Guide</h2>
<ul>
@@ -51,11 +57,11 @@ <h2 id="web-subtitle">Using and Extending Bespin</h2>
<li><a href="pluginguide/syntax.html">Syntax Highlighting</a></li>
<li><a href="pluginguide/keymapping.html">Keymapping</a></li>
</ul>
-<h2>Embedder's Guide</h2>
+<h2>User's Guide</h2>
<ul>
-<li><a href="embedding/index.html">Introduction</a></li>
-<li><a href="embedding/building.html">Creating a custom, embedded Bespin</a></li>
-<li><a href="embedding/appconfig.html">Application Configuration (Gluing Bespin Together)</a></li>
+<li><em>Important</em> <a href="userguide/server_roadmap.html">Bespin Server Roadmap</a></li>
+<li><a href="userguide/index.html">Introduction</a></li>
+<li><a href="userguide/vcs.html">Version Control Systems</a></li>
</ul>
<h2>Developer's Guide</h2>
<ul>
View
97 Bespin/BespinEmbedded/docs/pluginguide/template.html
@@ -64,16 +64,22 @@ <h2 id="web-subtitle">Template Engine</h2>
</pre></div>
-<h2>${...} in General Attributes</h2>
+<h2>${...} in Attributes and Content</h2>
<p>Any ${} element will be processed as a portion of Javascript, in the context of
-the object passed to the templates.name function (i.e. templates.bar in the
-example above)</p>
-<p>The 'save' attribute is a special attribute to record the current element. See
-below for more details.</p>
-<p>${...} can show up in elements and in text nodes, and will be processed
-accordingly. A ${...} block contains arbitrary Javascript, but should return
-something. Generally however it is recommended to stick to a dot path from
-an attribute passed to the template.</p>
+the first object passed to the templating function (In the example above the
+context would be <code>{ parent: this, contents: "world" }</code>)</p>
+<p>The <code>save</code>/<code>if</code>/<code>foreach</code> attributes have special meanings. See below for more
+details.</p>
+<p><code>${...}</code> can show up in elements and in HTML content. A <code>${...}</code> block contains
+arbitrary Javascript. Generally however it is recommended to stick to a dot path
+from an attribute passed to the template.</p>
+<p>It expected that <code>${...}</code> blocks will return strings when used in an attribute.
+When used in HTML content, <code>${...}</code> blocks can return either strings (which will
+be added to the DOM inside a TextNode (i.e. with HTML escaped) or they can
+return DOM elements, in which case the DOM element will be added to the tree.</p>
+<p>The following is not recommended (try to keep logic separate from content)
+however it should work:
+ <div>${document.createTextNode('BANG!')}</div></p>
<h2>save="${...}" Attributes</h2>
<p>The save attribute is special. It takes the current node at sets it into the
pointed to structure. In this case ${} is not arbitrary Javascript but a dot
@@ -113,17 +119,72 @@ <h2 id="web-subtitle">Template Engine</h2>
simpler.</p>
<p>It is very likely that the useCapture syntax will change in the future, probably
to something that does not invade the ${...} space possibly something more like
-<code>onfocus="${object.handler}" onfocususecapture="true"</code></p>
-<h2>Future</h2>
-<p>2 future directions are being considered for this template:
-<em> if="${some_boolean}" and loopFor="${some_array}" attributes. The former allows
- the template to prune some part of the output unless a condition is met. The
- latter allows a node to be repeated a number of times with different values
- for each member of the array.
-</em> 2-way templating. For form fill applications, it can be useful to allow
+<code>onfocus="${object.handler}" captureonfocus="true"</code></p>
+<h2>_***="${...}" Attributes</h2>
+<p>The Bespin Template engine uses the web browsers parser to interpret .htmlt
+file before we process the templates. This has a number of advantages in
+simplicity and the ability to work with the resulting DOM, however one drawback
+is that the browser may try to process certain elements before they are ready.
+For example:</p>
+<img src="${path}/thing.png"/>
+
+<p>This will the processed, and (assuming 'path' is correctly set) the right image
+will be displayed, however you may notice your browser giving a 404 message from
+${path}/thing.png as it has attempted to retrieve the image before the template
+process had a chance to substitute the correct path.</p>
+<p>The solution is to prefix the attribute name with an underscore ('_'). The
+template engine will remove the underscore automatically. For example:</p>
+<img _src="${path}/thing.png"/>
+
+<p>Should you wish to have an attribute in the resulting document prefixed with an
+underscore, simply begin your attribute name with 2 underscores. (Is this a
+common scenario? If you know of another scenario where attribute names are
+prefixed with _, please inform the Bespin-Core mailing list using
+[bespin-core at googlegroups dot com].</p>
+<h2>if="${some_boolean}" Attributes</h2>
+<p>If an element contains an 'if' attribute, then its value will be evaluated and
+if the result is 'falsey', then the entire element will be removed from the
+tree. This allows simple if statements.</p>
+<p>Example:</p>
+<div class="codehilite"><pre><span class="nt">&lt;div&gt;</span>
+<span class="nt">&lt;p</span> <span class="na">if=</span><span class="s">&quot;</span><span class="cp">${</span><span class="n">name</span> <span class="o">!==</span> <span class="n">null</span><span class="cp">}</span><span class="s">&gt;Hello, </span><span class="cp">${</span><span class="n">name</span><span class="cp">}</span><span class="s">&lt;/p&gt;</span>
+<span class="s">&lt;/div&gt;</span>
+
+<span class="s">templates.example({ name: &#39;Fred&#39; }); // &lt;div&gt;&lt;p&gt;Hello, Fred&lt;/p&gt;&lt;/div&gt;</span>
+<span class="s">templates.example({ }); // &lt;div&gt;&lt;/div&gt;</span>
+</pre></div>
+
+
+<p>In the second example, the entire 'p' element has been removed by processing
+the if attribute.</p>
+<h2>foreach="${some_array} Attributes</h2>
+<p>If an element contains a foreach attribute, then that element will be repeated
+in the final document once for each member of the array returned by the
+attribute value. The 'param' variable will be available, and set to the
+corresponding array member during the evaluation.</p>
+<p>Example:</p>
+<div class="codehilite"><pre><span class="nt">&lt;div</span> <span class="na">foreach=</span><span class="s">&quot;</span><span class="cp">${</span><span class="p">[</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span> <span class="p">]</span><span class="cp">}</span><span class="s">&quot;</span><span class="nt">&gt;</span><span class="cp">${</span><span class="n">param</span><span class="cp">}</span><span class="nt">&lt;/div&gt;</span>
+templates.example({ }); // <span class="nt">&lt;div&gt;</span>1<span class="nt">&lt;/div&gt;&lt;div&gt;</span>2<span class="nt">&lt;/div&gt;&lt;div&gt;</span>3<span class="nt">&lt;/div&gt;</span>
+</pre></div>
+
+
+<p>A future version of the template engine will likely allow you to alter the
+name of the variable to which array members are set, from the default 'param'.
+This will allow greater flexibility in processing nested loops.
+A natural syntax could be:
+ <div foreach="number in ${[ 1, 2, 3 ]}">${number}</div></p>
+<h2>Future and Questions</h2>
+<ul>
+<li>Should we have a way to recognize attributes that are special to the template
+ engine? What if a future HTML standard introduces an element with
+ if/save/foreach attributes?</li>
+<li>2-way templating. For form fill applications, it can be useful to allow
changes to input elements to be automatically reflected in the original
structure, or even for changes in the original structure to be reflected in
- the HTML. This last example is probably too complex for our purposes however.</p>
+ the HTML. It could be managed using #{} references rather then ${}. The
+ difficulty is in recognizing changes to DOM elements on all browsers.
+ This last example is probably too complex for our purposes however.</li>
+</ul>
</div>
<!-- / MAIN COLUMN -->
View
9 Bespin/BespinEmbedded/docs/releases/notes09.html
@@ -32,6 +32,15 @@ <h1 id="web-title">Bespin 0.9 ("Edison") Release Notes</h1>
<!-- MAIN COLUMN -->
<div id="maincol">
<p><a href="index.html">Up</a> - Next Release - <a href="notes08.html">Previous Release</a></p>
+<h2>0.9a2 (September 29, 2010) Changes</h2>
+<ul>
+<li>New jslint_command plugin. ctrl-shift-V or "jslint" from the command line
+ will check your code. It will notify if there are any errors.</li>
+<li>The diff highlighter is now included in the bookmarklet</li>
+<li>console logging within Bespin now works with the Firefox 4 Web Console</li>
+<li>Updated to a newer Traits.js for Chrome 6+ compatibility</li>
+<li>Other minor fixes</li>
+</ul>
<h2>Important Changes</h2>
<p>There has been a major plugin API change between 0.8 and 0.9. Please
see the "upgrade notes" later in this file.</p>
View
BIN Bespin/BespinEmbedded/docs/tutorials/ToolbarAsList.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
530 Bespin/BespinEmbedded/docs/tutorials/commands.html
@@ -0,0 +1,530 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8">
+
+ <title>Bespin Tutorials</title>
+
+ <link rel="stylesheet" type="text/css" href="../css/reset.css">
+ <link rel="stylesheet" type="text/css" href="../css/stylesheet.css" media="screen,projection">
+ <link rel="stylesheet" type="text/css" href="../css/colorful.css">
+</head>
+<body>
+
+<!-- MAIN CONTAINER -->
+<div id="main-container">
+
+<!-- MENU -->
+<ul id="menu">
+ <li><a href="../index.html" title="Home">Home</a></li>
+ <li><a href="../userguide/index.html" title="User Guide">Using Bespin</a></li>
+ <li><a href="../pluginguide/index.html" title="Plugin Guide">Creating Plugins</a></li>
+ <li><a href="../embedding/index.html" title="Embedding Bespin in your app">Embedding</a></li>
+ <li><a href="../devguide/index.html" title="Developer's Guide">Developing Bespin</a></li>
+</ul>
+<!-- / MENU -->
+
+<h1 id="web-title">Bespin Tutorials</h1>
+<h2 id="web-subtitle">Manipulating Text Through Commands</h2>
+
+<!-- INDEX PAGE -->
+
+<!-- MAIN COLUMN -->
+<div id="maincol">
+<h1>Introduction</h1>
+<p>This tutorial was originally written for Bespin 0.9.</p>
+<p>In this tutorial, we'll be creating new commands that allow Bespin to work
+with <a href="http://daringfireball.net/projects/markdown/">Markdown</a> formatted
+text.</p>
+<p>For this tutorial, <strong>you'll need the markdown_js plugin</strong> which is available
+from the Plugin Gallery.</p>
+<h2>Setting Up</h2>
+<p>With this tutorial, we're starting from the very basics. You'll need Python
+(preferably 2.6) to do custom Bespin plugin development. If you don't have
+Python already, you can get it <a href="http://python.org/">prebuilt for your platform</a>
+with little fuss.</p>
+<p>You'll also need Bespin Embedded, which you can get from the
+<a href="http://ftp.mozilla.org/pub/mozilla.org/labs/bespin/Embedded/">releases directory on ftp.mozilla.org</a>.</p>
+<p>Make a directory called <code>bespintutorial</code>. Uncompress the BespinEmbedded package
+in there and rename the directory from the tarfile <code>bespin</code> (so you'll have
+<code>bespintutorial/bespin/</code>). On a Mac, you can do these things from the Terminal
+command line:</p>
+<div class="codehilite"><pre><span class="nb">mkdir</span> <span class="n">bespintutorial</span>
+<span class="n">cd</span> <span class="n">bespintutorial</span>
+<span class="n">cp</span> <span class="o">~</span><span class="sr">/Downloads/</span><span class="n">BespinEmbedded</span><span class="o">-</span><span class="n">VERSION</span><span class="o">.</span><span class="n">tar</span><span class="o">.</span><span class="n">gz</span> <span class="o">.</span>
+<span class="n">tar</span> <span class="n">xzf</span> <span class="n">BespinEmbedded</span><span class="o">-</span><span class="n">VERSION</span><span class="o">.</span><span class="n">tar</span><span class="o">.</span><span class="n">gz</span>
+<span class="n">mv</span> <span class="n">BespinEmbedded</span><span class="o">-</span><span class="n">VERSION</span> <span class="n">bespin</span>
+</pre></div>
+
+
+<h2>The Manifest</h2>
+<p>Bespin's build tool, dryice, uses a "manifest" file in JSON format to describe
+what it needs to build and where to find all of the parts. Open up your
+text editor to create a file called <code>manifest.json</code> in the <code>bespintutorial</code>
+directory. Here's what will go into the file at this step:</p>
+<div class="codehilite"><pre><span class="p">{</span>
+ <span class="s2">&quot;output_dir&quot;</span><span class="o">:</span> <span class="s2">&quot;../build&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;plugins&quot;</span><span class="o">:</span> <span class="p">[</span><span class="s2">&quot;embedded&quot;</span><span class="p">],</span>
+ <span class="s2">&quot;search_path&quot;</span><span class="o">:</span> <span class="p">[</span><span class="s2">&quot;..&quot;</span><span class="p">]</span>
+<span class="p">}</span>
+</pre></div>
+
+
+<p>We'll be running the build from the <code>bespin</code> directory, so those <code>..</code> in
+the manifest are referring to the <code>bespintutorial</code> directory.</p>
+<p>Now, we'll fire up the dryice server. This command assumes at Python is
+on your path:</p>
+<div class="codehilite"><pre><span class="n">cd</span> <span class="n">bespin</span>
+<span class="n">python</span> <span class="n">dryice</span><span class="o">.</span><span class="n">py</span> <span class="o">-</span><span class="n">s</span> <span class="mi">8080</span> <span class="o">../</span><span class="n">manifest</span><span class="o">.</span><span class="n">json</span>
+</pre></div>
+
+
+<p>After running that command, you can open up your browser to
+http://localhost:8080/ and you should see the Bespin editor that dryice
+just built for us.</p>
+<p>Next, place the <code>markdown_js.js</code> file which you got from the Plugin Gallery
+into the <code>bespintutorial</code> directory.</p>
+<h2>Getting Our Plugin Going</h2>
+<p>Now, we'll create a new file called <code>markdown.js</code>. This is our Bespin plugin
+file. Bespin plugins all have a metadata section, so let's put that at the
+top of our file to get us going:</p>
+<div class="codehilite"><pre><span class="s2">&quot;define metadata&quot;</span><span class="p">;</span>
+<span class="p">({</span>
+ <span class="s2">&quot;dependencies&quot;</span><span class="o">:</span> <span class="p">{</span>
+ <span class="s2">&quot;markdown_js&quot;</span><span class="o">:</span> <span class="s2">&quot;0.1.2&quot;</span>
+ <span class="p">}</span>
+<span class="p">});</span>
+<span class="s2">&quot;end&quot;</span><span class="p">;</span>
+</pre></div>
+
+
+<p>So, that's our whole plugin for now. All we're saying is that our plugin
+depends on the <code>markdown_js</code> plugin (version 0.1.2). Now we have to tell
+dryice about our new plugin, so we'll add it to the plugins line
+of our manifest.json file:</p>
+<div class="codehilite"><pre><span class="s">&quot;plugins&quot;</span><span class="p">:</span> <span class="p">[</span><span class="s">&quot;embedded&quot;</span><span class="p">,</span> <span class="s">&quot;markdown&quot;</span><span class="p">],</span>
+</pre></div>
+
+
+<p>You should be able to reload http://localhost:8080/ and have things still work.</p>
+<h2>Making Our Plugin Do Something</h2>
+<p>Since we're going to be making commands, it would be most convenient for us
+at this point to have a command line. So, we'll add the <code>command_line</code>
+plugin to our manifest.json file:</p>
+<div class="codehilite"><pre><span class="s">&quot;plugins&quot;</span><span class="p">:</span> <span class="p">[</span><span class="s">&quot;embedded&quot;</span><span class="p">,</span> <span class="s">&quot;markdown&quot;</span><span class="p">,</span> <span class="s">&quot;command_line&quot;</span><span class="p">],</span>
+</pre></div>
+
+
+<p>Reload the page in your browser and you should see the command line at the
+bottom. I also like being able to press cmd-J (ctrl-J on Windows/Linux) to
+switch between the command line and the editor. The uicommands plugin gives
+us that, so let's enable that, too:</p>
+<div class="codehilite"><pre><span class="s">&quot;plugins&quot;</span><span class="p">:</span> <span class="p">[</span><span class="s">&quot;embedded&quot;</span><span class="p">,</span> <span class="s">&quot;markdown&quot;</span><span class="p">,</span> <span class="s">&quot;command_line&quot;</span><span class="p">,</span> <span class="s">&quot;uicommands&quot;</span><span class="p">],</span>
+</pre></div>
+
+
+<p>Now we're ready to make our first command. We're going to make a command
+that:</p>
+<ol>
+<li>converts the Markdown text we've entered to HTML</li>
+<li>puts that HTML in a new window so we can preview it.</li>
+</ol>
+<p>Let's write a function that does these things.</p>
+<div class="codehilite"><pre><span class="kd">var</span> <span class="nx">env</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;environment&#39;</span><span class="p">).</span><span class="nx">env</span><span class="p">;</span>
+<span class="kd">var</span> <span class="nx">markdown</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s2">&quot;markdown_js&quot;</span><span class="p">);</span>
+
+<span class="nx">exports</span><span class="p">.</span><span class="nx">preview</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">args</span><span class="p">,</span> <span class="nx">request</span><span class="p">)</span> <span class="p">{</span>
+ <span class="kd">var</span> <span class="nx">text</span> <span class="o">=</span> <span class="nx">env</span><span class="p">.</span><span class="nx">editor</span><span class="p">.</span><span class="nx">selectedText</span><span class="p">;</span>
+ <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">text</span><span class="p">)</span> <span class="p">{</span>
+ <span class="nx">text</span> <span class="o">=</span> <span class="nx">env</span><span class="p">.</span><span class="nx">editor</span><span class="p">.</span><span class="nx">value</span><span class="p">;</span>
+ <span class="p">}</span>
+ <span class="kd">var</span> <span class="nx">popup</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nx">open</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="s2">&quot;_blank&quot;</span><span class="p">,</span> <span class="s2">&quot;location=no,menubar=no&quot;</span><span class="p">);</span>
+ <span class="nx">popup</span><span class="p">.</span><span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">innerHTML</span> <span class="o">=</span> <span class="nx">markdown</span><span class="p">.</span><span class="nx">toHTML</span><span class="p">(</span><span class="nx">text</span><span class="p">);</span>
+ <span class="nx">request</span><span class="p">.</span><span class="nx">done</span><span class="p">();</span>
+<span class="p">};</span>
+</pre></div>
+
+
+<p>The first two lines import other modules that we'll be needing. The
+<code>environment</code> plugin is always available in Bespin, and the <code>env</code>
+variable inside of there is very handy, as we'll soon see. We also
+import the <code>markdown_js</code> module that we declared in our dependencies.
+We'll call it <code>markdown</code> when we use it in this module for convenience.</p>
+<p>If you're not familiar with <a href="http://commonjs.org/specs/modules/1.0/">CommonJS Modules</a>,
+you'll find that they're simple to work with. You use the <code>require</code> function to
+import modules and you put anything you want to be available outside of the
+module on the <code>exports</code> object. We're going to make a function called <code>preview</code>
+available from this module.</p>
+<p>Bespin command functions all take two parameters: <code>args</code> and <code>request</code>.
+<code>args</code> contains the incoming arguments to the command and <code>request</code> provides
+methods for working with this particular request from the user. Of these, the
+commands we'll be making here today only make use of <code>request.done()</code>, which
+signals that we have finished all of our processing.</p>
+<p>Now, let's focus on the body of the function:</p>
+<div class="codehilite"><pre><span class="kd">var</span> <span class="nx">text</span> <span class="o">=</span> <span class="nx">env</span><span class="p">.</span><span class="nx">editor</span><span class="p">.</span><span class="nx">selectedText</span><span class="p">;</span>
+<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">text</span><span class="p">)</span> <span class="p">{</span>
+ <span class="nx">text</span> <span class="o">=</span> <span class="nx">env</span><span class="p">.</span><span class="nx">editor</span><span class="p">.</span><span class="nx">value</span><span class="p">;</span>
+<span class="p">}</span>
+<span class="kd">var</span> <span class="nx">popup</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nx">open</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="s2">&quot;_blank&quot;</span><span class="p">,</span> <span class="s2">&quot;location=no,menubar=no&quot;</span><span class="p">);</span>
+<span class="nx">popup</span><span class="p">.</span><span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">innerHTML</span> <span class="o">=</span> <span class="nx">markdown</span><span class="p">.</span><span class="nx">toHTML</span><span class="p">(</span><span class="nx">text</span><span class="p">);</span>
+<span class="nx">request</span><span class="p">.</span><span class="nx">done</span><span class="p">();</span>
+</pre></div>
+
+
+<p>The first line gets us the currently selected text. If the user selected only
+a portion of the document, we'll preview that. The next line looks to see
+if there was any selected text. If there wasn't, then we just grab all of the
+text from the editor.</p>
+<p>Next, we use the standard window.open call to make a new window. A call to <code>markdown.toHTML</code> will give us the HTML version of our text and we drop
+that into our new window and we're all set!</p>
+<p>We need to register our new command with Bespin.</p>
+<p>Since we're going to create more than one Markdown related command, we'll
+plan to create a top-level <code>markdown</code> command with subcommands. The
+command we're working on now is <code>markdown preview</code>. We need to add
+a new <code>provides</code> section to our JSON metadata. Here's what that looks like:</p>
+<div class="codehilite"><pre><span class="s">&quot;provides&quot;</span><span class="p">:</span> <span class="p">[</span>
+ <span class="p">{</span>
+ <span class="s">&quot;ep&quot;</span><span class="p">:</span> <span class="s">&quot;command&quot;</span><span class="p">,</span>
+ <span class="s">&quot;name&quot;</span><span class="p">:</span> <span class="s">&quot;markdown&quot;</span><span class="p">,</span>
+ <span class="s">&quot;description&quot;</span><span class="p">:</span> <span class="s">&quot;commands for working with markdown files&quot;</span>
+ <span class="p">},</span>
+ <span class="p">{</span>
+ <span class="s">&quot;ep&quot;</span><span class="p">:</span> <span class="s">&quot;command&quot;</span><span class="p">,</span>
+ <span class="s">&quot;name&quot;</span><span class="p">:</span> <span class="s">&quot;markdown preview&quot;</span><span class="p">,</span>
+ <span class="s">&quot;description&quot;</span><span class="p">:</span> <span class="s">&quot;preview the HTML form of this markdown text&quot;</span><span class="p">,</span>
+ <span class="s">&quot;pointer&quot;</span><span class="p">:</span> <span class="s">&quot;#preview&quot;</span>
+ <span class="p">}</span>
+<span class="p">]</span>
+</pre></div>
+
+
+<p><code>provides</code> gives a list of extensions that are provided by this plugin.
+Each of those will have an <code>ep</code> at a minimum. That's the "extension point"
+that we're plugging into. Our first extension is a command and we give
+the command a name (which is what the user types) and a description that
+will appear in help text.</p>
+<p>The second extension is for our preview command. It has a name and description
+as well. But, since this command is not just a holder for other commands,
+it also has a <code>pointer</code>. The <code>pointer</code> tells Bespin where to find the object
+(in this case, a function) for the extension. <code>#preview</code> is equivalent to
+<code>markdown:index#preview</code> which means the <code>preview</code> function in the <code>index</code>
+module in the <code>markdown</code> plugin.</p>
+<p>Your complete file should now look like this:</p>
+<div class="codehilite"><pre><span class="s">&quot;define metadata&quot;</span><span class="p">;</span>
+<span class="p">({</span>
+ <span class="s">&quot;dependencies&quot;</span><span class="p">:</span> <span class="p">{</span>
+ <span class="s">&quot;markdown_js&quot;</span><span class="p">:</span> <span class="s">&quot;0.1.2&quot;</span>
+ <span class="p">},</span>
+ <span class="s">&quot;provides&quot;</span><span class="p">:</span> <span class="p">[</span>
+ <span class="p">{</span>
+ <span class="s">&quot;ep&quot;</span><span class="p">:</span> <span class="s">&quot;command&quot;</span><span class="p">,</span>
+ <span class="s">&quot;name&quot;</span><span class="p">:</span> <span class="s">&quot;markdown&quot;</span><span class="p">,</span>
+ <span class="s">&quot;description&quot;</span><span class="p">:</span> <span class="s">&quot;commands for working with markdown files&quot;</span>
+ <span class="p">},</span>
+ <span class="p">{</span>
+ <span class="s">&quot;ep&quot;</span><span class="p">:</span> <span class="s">&quot;command&quot;</span><span class="p">,</span>
+ <span class="s">&quot;name&quot;</span><span class="p">:</span> <span class="s">&quot;markdown preview&quot;</span><span class="p">,</span>
+ <span class="s">&quot;description&quot;</span><span class="p">:</span> <span class="s">&quot;preview the HTML form of this markdown text&quot;</span><span class="p">,</span>
+ <span class="s">&quot;pointer&quot;</span><span class="p">:</span> <span class="s">&quot;#preview&quot;</span>
+ <span class="p">}</span>
+ <span class="p">]</span>
+<span class="p">});</span>
+<span class="s">&quot;end&quot;</span><span class="p">;</span>
+
+<span class="n">var</span> <span class="n">env</span> <span class="o">=</span> <span class="nb">require</span><span class="p">(</span><span class="s">&#39;environment&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">env</span><span class="p">;</span>
+<span class="n">var</span> <span class="n">markdown</span> <span class="o">=</span> <span class="nb">require</span><span class="p">(</span><span class="s">&quot;markdown_js&quot;</span><span class="p">);</span>
+
+<span class="n">exports</span><span class="o">.</span><span class="n">preview</span> <span class="o">=</span> <span class="n">function</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="n">request</span><span class="p">)</span> <span class="p">{</span>
+ <span class="n">var</span> <span class="n">text</span> <span class="o">=</span> <span class="n">env</span><span class="o">.</span><span class="n">editor</span><span class="o">.</span><span class="n">selectedText</span><span class="p">;</span>
+ <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">text</span><span class="p">)</span> <span class="p">{</span>
+ <span class="n">text</span> <span class="o">=</span> <span class="n">env</span><span class="o">.</span><span class="n">editor</span><span class="o">.</span><span class="n">value</span><span class="p">;</span>
+ <span class="p">}</span>
+ <span class="n">var</span> <span class="n">popup</span> <span class="o">=</span> <span class="n">window</span><span class="o">.</span><span class="nb">open</span><span class="p">(</span><span class="s">&quot;&quot;</span><span class="p">,</span> <span class="s">&quot;_blank&quot;</span><span class="p">,</span> <span class="s">&quot;location=no,menubar=no&quot;</span><span class="p">);</span>
+ <span class="n">popup</span><span class="o">.</span><span class="n">document</span><span class="o">.</span><span class="n">body</span><span class="o">.</span><span class="n">innerHTML</span> <span class="o">=</span> <span class="n">markdown</span><span class="o">.</span><span class="n">toHTML</span><span class="p">(</span><span class="n">text</span><span class="p">);</span>
+ <span class="n">request</span><span class="o">.</span><span class="n">done</span><span class="p">();</span>
+<span class="p">};</span>
+</pre></div>
+
+
+<p>Let's come up with some sample Markdown to use. How about this:</p>
+<div class="codehilite"><pre><span class="c1"># Markdown Test #</span>
+
+<span class="n">This</span> <span class="n">is</span> <span class="n">a</span> <span class="o">*</span><span class="n">simple</span><span class="o">*</span> <span class="n">test</span> <span class="n">of</span> <span class="n">Markdown</span><span class="o">.</span>
+
+<span class="o">*</span> <span class="n">one</span>
+<span class="o">*</span> <span class="n">two</span>
+<span class="o">*</span> <span class="n">three</span>
+</pre></div>
+
+
+<p>Reload your browser, select all of the text and paste in that text. Then,
+jump down to the command line and run the <code>markdown preview</code> command. You
+should see a new window popup with the HTML version of the text there.</p>
+<p>Congratulations! You've extended Bespin with a new command.</p>
+<h2>Keyboard Shortcut</h2>
+<p>Previewing the HTML seems like a very useful feature. Why don't we add a
+keyboard shortcut so that we don't need to go to the command line each time.
+To do this, we just need to add a <code>key</code> to the <code>markdown preview</code> metadata,
+like so:</p>
+<div class="codehilite"><pre><span class="p">{</span>
+ <span class="s">&quot;ep&quot;</span><span class="p">:</span> <span class="s">&quot;command&quot;</span><span class="p">,</span>
+ <span class="s">&quot;name&quot;</span><span class="p">:</span> <span class="s">&quot;markdown preview&quot;</span><span class="p">,</span>
+ <span class="s">&quot;description&quot;</span><span class="p">:</span> <span class="s">&quot;preview the HTML form of this markdown text&quot;</span><span class="p">,</span>
+ <span class="s">&quot;key&quot;</span><span class="p">:</span> <span class="s">&quot;ctrl_shift_p&quot;</span><span class="p">,</span>
+ <span class="s">&quot;pointer&quot;</span><span class="p">:</span> <span class="s">&quot;#preview&quot;</span>
+<span class="p">}</span>
+</pre></div>
+
+
+<p>Now, cmd-shift-P on the Mac or ctrl-shift-P on Windows/Linux will run
+the <code>markdown preview</code> command. This also means that we can run the
+<code>markdown preview</code> command even if we don't have the command line plugin
+in our build.</p>
+<p>An aside about keyboard shortcuts: the <code>key</code> defined in command metadata
+like this is the lowest priority keyboard binding. A keymapping plugin can
+redefine the keys as can user preferences.</p>
+<h2>Replacing Text</h2>
+<p>One more common requirement of commands is that they need to be able to
+manipulate the text in some fashion and then put the manipulated version
+back into the editor.</p>
+<p>We'll make a <code>markdown convert</code> command that converts the text to HTML
+and then puts the text back into the editor. As before, we'll start
+by writing a function that does this conversion and we'll place it at
+the bottom of our file:</p>
+<div class="codehilite"><pre><span class="n">exports</span><span class="o">.</span><span class="n">convert</span> <span class="o">=</span> <span class="n">function</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="n">request</span><span class="p">)</span> <span class="p">{</span>
+ <span class="n">var</span> <span class="n">allOrSelection</span> <span class="o">=</span> <span class="s">&#39;selectedText&#39;</span><span class="p">;</span>
+ <span class="n">var</span> <span class="n">text</span> <span class="o">=</span> <span class="n">env</span><span class="o">.</span><span class="n">editor</span><span class="o">.</span><span class="n">selectedText</span><span class="p">;</span>
+ <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">text</span><span class="p">)</span> <span class="p">{</span>
+ <span class="n">allOrSelection</span> <span class="o">=</span> <span class="s">&#39;value&#39;</span><span class="p">;</span>
+ <span class="n">text</span> <span class="o">=</span> <span class="n">env</span><span class="o">.</span><span class="n">editor</span><span class="o">.</span><span class="n">value</span><span class="p">;</span>
+ <span class="p">}</span>
+ <span class="n">var</span> <span class="n">html</span> <span class="o">=</span> <span class="n">markdown</span><span class="o">.</span><span class="n">toHTML</span><span class="p">(</span><span class="n">text</span><span class="p">);</span>
+ <span class="n">env</span><span class="o">.</span><span class="n">editor</span><span class="p">[</span><span class="n">allOrSelection</span><span class="p">]</span> <span class="o">=</span> <span class="n">html</span><span class="p">;</span>
+ <span class="n">request</span><span class="o">.</span><span class="n">done</span><span class="p">();</span>
+<span class="p">};</span>
+</pre></div>
+
+
+<p>In this function, we're going to do the same kind of thing we did in the
+<code>preview</code> function. We'll work with the user's selection, if there is one,
+and the complete text otherwise. In this case, we need to keep track
+of which it was so that, when we do the replacement, we're only replacing
+the text that the user had selected.</p>
+<p>Once we've gotten our text, we can use <code>markdown.toHTML</code> to do the conversion.
+Then, we put the text back into the editor (going into either <code>selectedText</code>
+or <code>value</code>, depending on where the text came from originally).</p>
+<p>We need to tell Bespin about our new command, so we'll add another object
+to the <code>provides</code> part of our metadata.</p>
+<div class="codehilite"><pre><span class="p">{</span>
+ <span class="s2">&quot;ep&quot;</span><span class="o">:</span> <span class="s2">&quot;command&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;name&quot;</span><span class="o">:</span> <span class="s2">&quot;markdown convert&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;description&quot;</span><span class="o">:</span> <span class="s2">&quot;convert the selected text to HTML&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;pointer&quot;</span><span class="o">:</span> <span class="s2">&quot;#convert&quot;</span>
+<span class="p">}</span>
+</pre></div>
+
+
+<p>Looks just like the <code>markdown preview</code> command, doesn't it?</p>
+<p>Reload the page in your browser, paste in the sample markdown text and
+then run the <code>markdown convert</code> command. You should see the text converted
+to HTML. Try converting just a section of the text, and you'll see that just
+that portion of the file is modified.</p>
+<p>That was easy, wasn't it?</p>
+<h2>Undo</h2>
+<p>Try converting the Markdown to HTML and then pressing cmd/ctrl-Z.</p>
+<h2>Submitting to the Bespin Plugin Gallery</h2>
+<p>Once you've completed creating a plugin that you want to share with the
+rest of the world, you should add a little more to the metadata before
+uploading your plugin to the <a href="http://bespinplugins.mozillalabs.com/">Bespin Plugin Gallery</a>.</p>
+<p>We'll add version, license and maintainer information:</p>
+<div class="codehilite"><pre><span class="s">&quot;version&quot;</span><span class="p">:</span> <span class="s">&quot;1.0.0&quot;</span><span class="p">,</span>
+<span class="s">&quot;maintainers&quot;</span><span class="p">:</span> <span class="p">[</span>
+ <span class="p">{</span>
+ <span class="s">&quot;name&quot;</span><span class="p">:</span> <span class="s">&quot;Kevin Dangoor&quot;</span><span class="p">,</span>
+ <span class="s">&quot;email&quot;</span><span class="p">:</span> <span class="s">&quot;kid@blazingthings.com&quot;</span><span class="p">,</span>
+ <span class="s">&quot;web&quot;</span><span class="p">:</span> <span class="s">&quot;http://blueskyonmars.com/&quot;</span>
+ <span class="p">}</span>
+<span class="p">],</span>
+<span class="s">&quot;licenses&quot;</span><span class="p">:</span> <span class="p">[</span>
+ <span class="p">{</span>
+ <span class="s">&quot;type&quot;</span><span class="p">:</span> <span class="s">&quot;MPL&quot;</span><span class="p">,</span>
+ <span class="s">&quot;url&quot;</span><span class="p">:</span> <span class="s">&quot;http://www.mozilla.org/MPL/MPL-1.1.html&quot;</span>
+ <span class="p">},</span>
+ <span class="p">{</span>
+ <span class="s">&quot;type&quot;</span><span class="p">:</span> <span class="s">&quot;GPL&quot;</span><span class="p">,</span>
+ <span class="s">&quot;url&quot;</span><span class="p">:</span> <span class="s">&quot;http://creativecommons.org/licenses/GPL/2.0/&quot;</span>
+ <span class="p">},</span>
+ <span class="p">{</span>
+ <span class="s">&quot;type&quot;</span><span class="p">:</span> <span class="s">&quot;LGPL&quot;</span><span class="p">,</span>
+ <span class="s">&quot;url&quot;</span><span class="p">:</span> <span class="s">&quot;http://creativecommons.org/licenses/LGPL/2.1/&quot;</span>
+ <span class="p">}</span>
+<span class="p">]</span>
+</pre></div>
+
+
+<p>Bespin Plugin metadata is actually a superset of the
+<a href="http://wiki.commonjs.org/wiki/Packages/1.0">CommonJS package</a>
+metadata. As specified there, the version numbers should follow
+the <a href="http://semver.org/">Semantic Versioning</a> numbering so that
+useful information about compatibility can be picked up from the
+version number alone.</p>
+<p>I added myself as a maintainer and made this plugin available under
+the tri-license that Bespin itself is available under.</p>
+<p>With all of this metadata in place, the final plugin file looks like this:</p>
+<div class="codehilite"><pre><span class="s">&quot;define metadata&quot;</span><span class="p">;</span>
+<span class="p">({</span>
+ <span class="s">&quot;dependencies&quot;</span><span class="p">:</span> <span class="p">{</span>
+ <span class="s">&quot;markdown_js&quot;</span><span class="p">:</span> <span class="s">&quot;0.1.2&quot;</span>
+ <span class="p">},</span>
+ <span class="s">&quot;provides&quot;</span><span class="p">:</span> <span class="p">[</span>
+ <span class="p">{</span>
+ <span class="s">&quot;ep&quot;</span><span class="p">:</span> <span class="s">&quot;command&quot;</span><span class="p">,</span>
+ <span class="s">&quot;name&quot;</span><span class="p">:</span> <span class="s">&quot;markdown&quot;</span><span class="p">,</span>
+ <span class="s">&quot;description&quot;</span><span class="p">:</span> <span class="s">&quot;commands for working with markdown files&quot;</span>
+ <span class="p">},</span>
+ <span class="p">{</span>
+ <span class="s">&quot;ep&quot;</span><span class="p">:</span> <span class="s">&quot;command&quot;</span><span class="p">,</span>
+ <span class="s">&quot;name&quot;</span><span class="p">:</span> <span class="s">&quot;markdown preview&quot;</span><span class="p">,</span>
+ <span class="s">&quot;description&quot;</span><span class="p">:</span> <span class="s">&quot;preview the HTML form of this markdown text&quot;</span><span class="p">,</span>
+ <span class="s">&quot;key&quot;</span><span class="p">:</span> <span class="s">&quot;ctrl_shift_p&quot;</span><span class="p">,</span>
+ <span class="s">&quot;pointer&quot;</span><span class="p">:</span> <span class="s">&quot;#preview&quot;</span>
+ <span class="p">},</span>
+ <span class="p">{</span>
+ <span class="s">&quot;ep&quot;</span><span class="p">:</span> <span class="s">&quot;command&quot;</span><span class="p">,</span>
+ <span class="s">&quot;name&quot;</span><span class="p">:</span> <span class="s">&quot;markdown convert&quot;</span><span class="p">,</span>
+ <span class="s">&quot;description&quot;</span><span class="p">:</span> <span class="s">&quot;convert the selected text to HTML&quot;</span><span class="p">,</span>
+ <span class="s">&quot;pointer&quot;</span><span class="p">:</span> <span class="s">&quot;#convert&quot;</span>
+ <span class="p">}</span>
+ <span class="p">],</span>
+ <span class="s">&quot;version&quot;</span><span class="p">:</span> <span class="s">&quot;1.0.0&quot;</span><span class="p">,</span>
+ <span class="s">&quot;maintainers&quot;</span><span class="p">:</span> <span class="p">[</span>
+ <span class="p">{</span>
+ <span class="s">&quot;name&quot;</span><span class="p">:</span> <span class="s">&quot;Kevin Dangoor&quot;</span><span class="p">,</span>
+ <span class="s">&quot;email&quot;</span><span class="p">:</span> <span class="s">&quot;kid@blazingthings.com&quot;</span><span class="p">,</span>
+ <span class="s">&quot;web&quot;</span><span class="p">:</span> <span class="s">&quot;http://blueskyonmars.com/&quot;</span>
+ <span class="p">}</span>
+ <span class="p">],</span>
+ <span class="s">&quot;licenses&quot;</span><span class="p">:</span> <span class="p">[</span>
+ <span class="p">{</span>
+ <span class="s">&quot;type&quot;</span><span class="p">:</span> <span class="s">&quot;MPL&quot;</span><span class="p">,</span>
+ <span class="s">&quot;url&quot;</span><span class="p">:</span> <span class="s">&quot;http://www.mozilla.org/MPL/MPL-1.1.html&quot;</span>
+ <span class="p">},</span>
+ <span class="p">{</span>
+ <span class="s">&quot;type&quot;</span><span class="p">:</span> <span class="s">&quot;GPL&quot;</span><span class="p">,</span>
+ <span class="s">&quot;url&quot;</span><span class="p">:</span> <span class="s">&quot;http://creativecommons.org/licenses/GPL/2.0/&quot;</span>
+ <span class="p">},</span>
+ <span class="p">{</span>
+ <span class="s">&quot;type&quot;</span><span class="p">:</span> <span class="s">&quot;LGPL&quot;</span><span class="p">,</span>
+ <span class="s">&quot;url&quot;</span><span class="p">:</span> <span class="s">&quot;http://creativecommons.org/licenses/LGPL/2.1/&quot;</span>
+ <span class="p">}</span>
+ <span class="p">]</span>
+<span class="p">});</span>
+<span class="s">&quot;end&quot;</span><span class="p">;</span>
+
+<span class="n">var</span> <span class="n">env</span> <span class="o">=</span> <span class="nb">require</span><span class="p">(</span><span class="s">&#39;environment&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">env</span><span class="p">;</span>
+<span class="n">var</span> <span class="n">markdown</span> <span class="o">=</span> <span class="nb">require</span><span class="p">(</span><span class="s">&quot;markdown_js&quot;</span><span class="p">);</span>
+
+<span class="n">exports</span><span class="o">.</span><span class="n">preview</span> <span class="o">=</span> <span class="n">function</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="n">request</span><span class="p">)</span> <span class="p">{</span>
+ <span class="n">var</span> <span class="n">text</span> <span class="o">=</span> <span class="n">env</span><span class="o">.</span><span class="n">editor</span><span class="o">.</span><span class="n">selectedText</span><span class="p">;</span>
+ <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">text</span><span class="p">)</span> <span class="p">{</span>
+ <span class="n">text</span> <span class="o">=</span> <span class="n">env</span><span class="o">.</span><span class="n">editor</span><span class="o">.</span><span class="n">value</span><span class="p">;</span>
+ <span class="p">}</span>
+ <span class="n">var</span> <span class="n">popup</span> <span class="o">=</span> <span class="n">window</span><span class="o">.</span><span class="nb">open</span><span class="p">(</span><span class="s">&quot;&quot;</span><span class="p">,</span> <span class="s">&quot;_blank&quot;</span><span class="p">,</span> <span class="s">&quot;location=no,menubar=no&quot;</span><span class="p">);</span>
+ <span class="n">popup</span><span class="o">.</span><span class="n">document</span><span class="o">.</span><span class="n">body</span><span class="o">.</span><span class="n">innerHTML</span> <span class="o">=</span> <span class="n">markdown</span><span class="o">.</span><span class="n">toHTML</span><span class="p">(</span><span class="n">text</span><span class="p">);</span>
+ <span class="n">request</span><span class="o">.</span><span class="n">done</span><span class="p">();</span>
+<span class="p">};</span>
+
+<span class="n">exports</span><span class="o">.</span><span class="n">convert</span> <span class="o">=</span> <span class="n">function</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="n">request</span><span class="p">)</span> <span class="p">{</span>
+ <span class="n">var</span> <span class="n">allOrSelection</span> <span class="o">=</span> <span class="s">&#39;selectedText&#39;</span><span class="p">;</span>
+ <span class="n">var</span> <span class="n">text</span> <span class="o">=</span> <span class="n">env</span><span class="o">.</span><span class="n">editor</span><span class="o">.</span><span class="n">selectedText</span><span class="p">;</span>
+ <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">text</span><span class="p">)</span> <span class="p">{</span>
+ <span class="n">allOrSelection</span> <span class="o">=</span> <span class="s">&#39;value&#39;</span><span class="p">;</span>
+ <span class="n">text</span> <span class="o">=</span> <span class="n">env</span><span class="o">.</span><span class="n">editor</span><span class="o">.</span><span class="n">value</span><span class="p">;</span>
+ <span class="p">}</span>
+ <span class="n">var</span> <span class="n">html</span> <span class="o">=</span> <span class="n">markdown</span><span class="o">.</span><span class="n">toHTML</span><span class="p">(</span><span class="n">text</span><span class="p">);</span>
+ <span class="n">env</span><span class="o">.</span><span class="n">editor</span><span class="p">[</span><span class="n">allOrSelection</span><span class="p">]</span> <span class="o">=</span> <span class="n">html</span><span class="p">;</span>
+ <span class="n">request</span><span class="o">.</span><span class="n">done</span><span class="p">();</span>
+<span class="p">};</span>
+</pre></div>
+
+
+<p>We can upload this single .js file to the plugin gallery to share it with others.
+Once we do, we'll have a change to add images and further description of the
+plugin if we wish. You can actually add a description to the plugin metadata
+itself, if you wish.</p>
+<h2>The End</h2>
+<p>In this tutorial, we created a brand new plugin that leveraged an existing
+JavaScript library to do useful text transformation in Bespin. Key concepts
+covered:</p>
+<ul>
+<li>using dryice server mode to test new plugins</li>
+<li>plugin structure and metadata</li>
+<li>the mechanics of creating an extension</li>
+<li>how to write command extensions</li>
+<li>how to manipulate the text in the editor</li>
+</ul>
+</div>
+<!-- / MAIN COLUMN -->
+
+<!-- SIDEBAR -->
+<div id="sidebar">
+
+
+
+
+
+
+
+
+
+
+</div>
+<!-- / SIDEBAR -->
+
+<!-- / MAIN CONTAINER -->
+</div>
+
+<!-- FOOTER -->
+<div id="footer">
+ <!-- COLUMN ONE -->
+ <div>
+ <h2 class="compact">Useful Links</h2>
+ <ul class="compact">
+ <li><a href="http://mozillalabs.com/bespin/">Bespin project home page</a></li>
+ <li><a href="https://wiki.mozilla.org/Labs/Bespin">Wiki</a></li>
+ </ul>
+ </div>
+ <!-- / COLUMN ONE -->
+
+ <!-- COLUMN TWO -->
+ <div>
+ <h2 class="compact">Developer Resources</h2>
+ <ul class="compact">
+ <li><a href="http://hg.mozilla.org/labs/bespinclient/">Main Code Repository</a></li>
+ <li><a href="http://hg.mozilla.org/labs/bespinserver/">Python server repository</a></li>
+ <li><a href="http://groups.google.com/group/bespin-core/">bespin-core mailing list for developers</a></li>
+ <li><a href="http://groups.google.com/group/bespin-commits/">bespin-commits mailing list for repository commit messages</a></li>
+ <li><a href="https://bugzilla.mozilla.org/buglist.cgi?product=bespin">Bug List</a></li>
+ </ul>
+ </div>
+ <!-- / COLUMN TWO -->
+
+ <!-- COLUMN THREE -->
+ <div>
+ <h2 class="compact">Get Help</h2>
+ <ul class="compact">
+ <li>The <a href="http://groups.google.com/group/bespin/">Bespin mailing list</a></li>
+ <li>Via IRC: <a href="irc://irc.mozilla.org/bespin">#bespin on irc.mozilla.org</a></li>
+ </ul>
+
+ <h2 class="compact">Documentation Template</h2>
+ <ul class="compact">
+ <li>Adapted from a design by <a href="http://www.mgrabovsky.is-game.com/">Matěj Grabovský</a></li>
+ </ul>
+ </div>
+ <!-- / COLUMN THREE -->
+</div>
+<!-- / FOOTER -->
+
+</body>
+</html>
View
510 Bespin/BespinEmbedded/docs/tutorials/gui.html
@@ -0,0 +1,510 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8">
+
+ <title>Bespin Tutorials</title>
+
+ <link rel="stylesheet" type="text/css" href="../css/reset.css">
+ <link rel="stylesheet" type="text/css" href="../css/stylesheet.css" media="screen,projection">
+ <link rel="stylesheet" type="text/css" href="../css/colorful.css">
+</head>
+<body>
+
+<!-- MAIN CONTAINER -->
+<div id="main-container">
+
+<!-- MENU -->
+<ul id="menu">
+ <li><a href="../index.html" title="Home">Home</a></li>
+ <li><a href="../userguide/index.html" title="User Guide">Using Bespin</a></li>
+ <li><a href="../pluginguide/index.html" title="Plugin Guide">Creating Plugins</a></li>
+ <li><a href="../embedding/index.html" title="Embedding Bespin in your app">Embedding</a></li>
+ <li><a href="../devguide/index.html" title="Developer's Guide">Developing Bespin</a></li>
+</ul>
+<!-- / MENU -->
+
+<h1 id="web-title">Bespin Tutorials</h1>
+<h2 id="web-subtitle">Adding to the GUI</h2>
+
+<!-- INDEX PAGE -->
+
+<!-- MAIN COLUMN -->
+<div id="maincol">
+<h1>Introduction</h1>
+<p>Since Bespin is a webapp, any Bespin command could conceivably pop up some bit
+of user interface to interact with the user. It's just a matter of creating some
+DOM nodes and placing them on the screen.</p>
+<p>But, if you want something a bit more persistent and integrated, you'll need
+to learn a bit about how Bespin's GUI is put together. That's what this tutorial
+is about.</p>
+<p>At the same time, we're going to talk about how Bespin plugins can themselves
+be pluggable.</p>
+<p>In this tutorial, we assume that you're already familiar with using dryice and
+the basics of making plugins. We're also going to assume a directory structure
+like the one from the <a href="commands.html">commands tutorial</a>.</p>
+<p>By the end of this tutorial, we'll have something that looks toolbar-like.
+We're not trying to create a fully-functional toolbar here, because the
+focus is on hooking in to Bespin's GUI.</p>
+<p>This tutorial should work with Bespin 0.9a1 or later. However, there
+is a <strong>bug in Firefox 3.6.x that will cause the toolbar to not display
+properly</strong>. Bespin 0.9a2 has a workaround for this, and the bug itself
+is fixed in Firefox versions after 3.6.x.</p>
+<h2>Creating Our Plugin</h2>
+<p>As with the commands tutorial, we're assuming that you're working within a
+directory called <code>bespintutorial</code> that has Bespin itself in a subdirectory
+called <code>bespin</code>.</p>
+<p>In plugins that have user interface elements, you will almost always need
+to create a "multi file plugin". That just means we'll be creating a
+directory rather than a single .js file.</p>
+<p>We'll create a directory called <code>tutorialtoolbar</code>. To turn it into a plugin,
+we need to create a file called <code>package.json</code> in the <code>tutorialtoolbar</code>
+directory.</p>
+<p>We also need a dryice manifest so that we can see our plugin in action.
+Create a file called <code>toolbar.json</code> in the <code>bespintutorial</code> directory.
+Here's what we'll put in it to start with:</p>
+<div class="codehilite"><pre><span class="p">{</span>
+ <span class="s2">&quot;output_dir&quot;</span><span class="o">:</span> <span class="s2">&quot;../build&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;plugins&quot;</span><span class="o">:</span> <span class="p">[</span><span class="s2">&quot;embedded&quot;</span><span class="p">,</span> <span class="s2">&quot;tutorialtoolbar&quot;</span><span class="p">],</span>
+ <span class="s2">&quot;search_path&quot;</span><span class="o">:</span> <span class="p">[</span><span class="s2">&quot;..&quot;</span><span class="p">]</span>
+<span class="p">}</span>
+</pre></div>
+
+
+<p>Switch to the <code>bespin</code> directory and run:</p>
+<div class="codehilite"><pre><span class="n">python</span> <span class="n">dryice</span><span class="o">.</span><span class="n">py</span> <span class="o">-</span><span class="n">s</span> <span class="mi">8080</span> <span class="o">../</span><span class="n">toolbar</span><span class="o">.</span><span class="n">json</span>
+</pre></div>
+
+
+<p>You shouldn't get any errors from dryice. That means that it was able to find
+our tutorialtoolbar plugin. If you open your browser to http://localhost:8080/,
+you'll see a normal looking Bespin. Now we just need to put something in our
+plugin.</p>
+<h2>Creating A Simple View</h2>
+<p>For a first step, we'll just toss a string up on the screen. In the
+<code>tutorialtoolbar</code> directory, create a new file called <code>index.js</code>.
+Here's how our toolbar component will start out:</p>
+<div class="codehilite"><pre><span class="nx">exports</span><span class="p">.</span><span class="nx">ToolbarView</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+ <span class="kd">var</span> <span class="nx">elem</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s2">&quot;div&quot;</span><span class="p">);</span>
+ <span class="nx">elem</span><span class="p">.</span><span class="nx">innerHTML</span> <span class="o">=</span> <span class="s2">&quot;&lt;b&gt;Toolbar!&lt;/b&gt;&quot;</span><span class="p">;</span>
+ <span class="k">this</span><span class="p">.</span><span class="nx">element</span> <span class="o">=</span> <span class="nx">elem</span><span class="p">;</span>
+<span class="p">};</span>
+</pre></div>
+
+
+<p>We're creating a <code>Toolbar</code> class. When a new <code>Toolbar</code> is created,
+it gets a new element which just has our string in it. We
+set that to <code>element</code> on the instance. This is the key to GUI components
+that are integrated into Bespin's UI: they just offer up an <code>element</code>
+that Bespin will put in place.</p>
+<p>The next step is telling the Bespin system about our new component.
+We do that in the <code>package.json</code> file, which will now look like this:</p>
+<div class="codehilite"><pre><span class="p">{</span>
+ <span class="s2">&quot;provides&quot;</span><span class="o">:</span> <span class="p">[</span>
+ <span class="p">{</span>
+ <span class="s2">&quot;ep&quot;</span><span class="o">:</span> <span class="s2">&quot;factory&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;name&quot;</span><span class="o">:</span> <span class="s2">&quot;tutorialtoolbar&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;action&quot;</span><span class="o">:</span> <span class="s2">&quot;new&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;pointer&quot;</span><span class="o">:</span> <span class="s2">&quot;#ToolbarView&quot;</span>
+ <span class="p">}</span>
+ <span class="p">]</span>
+<span class="p">}</span>
+</pre></div>
+
+
+<p>The factory extension point is used for extensions that provide components
+for Bespin to automatically instantiate. That may sound kind of vague,
+but you'll see in a moment that it's actually easy to use. The <code>action</code>
+tells Bespin that it's going to be creating a new instance and the
+<code>pointer</code> is telling Bespin to look in the tutorialtoolbar plugin's
+<code>index</code> module for something called <code>ToolbarView</code>.</p>
+<p>We've written code that will generate our initial toolbar and we've told
+Bespin that this is available. The next step is to tell Bespin to put
+one into the UI. This can be done either in the dryice manifest file or
+even at runtime when <code>useBespin</code> is called. We'll do it in the manifest
+file (<code>toolbar.json</code>). Here's the new manifest:</p>
+<div class="codehilite"><pre><span class="p">{</span>
+ <span class="s2">&quot;output_dir&quot;</span><span class="o">:</span> <span class="s2">&quot;../build&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;plugins&quot;</span><span class="o">:</span> <span class="p">[</span><span class="s2">&quot;embedded&quot;</span><span class="p">,</span> <span class="s2">&quot;tutorialtoolbar&quot;</span><span class="p">],</span>
+ <span class="s2">&quot;search_path&quot;</span><span class="o">:</span> <span class="p">[</span><span class="s2">&quot;..&quot;</span><span class="p">],</span>
+ <span class="s2">&quot;config&quot;</span><span class="o">:</span> <span class="p">{</span>
+ <span class="s2">&quot;objects&quot;</span><span class="o">:</span> <span class="p">{</span>
+ <span class="s2">&quot;toolbar&quot;</span><span class="o">:</span> <span class="p">{</span>
+ <span class="s2">&quot;factory&quot;</span><span class="o">:</span> <span class="s2">&quot;tutorialtoolbar&quot;</span>
+ <span class="p">}</span>
+ <span class="p">},</span>
+ <span class="s2">&quot;gui&quot;</span><span class="o">:</span> <span class="p">{</span>
+ <span class="s2">&quot;north&quot;</span><span class="o">:</span> <span class="p">{</span>
+ <span class="s2">&quot;component&quot;</span><span class="o">:</span> <span class="s2">&quot;toolbar&quot;</span>
+ <span class="p">}</span>
+ <span class="p">}</span>
+ <span class="p">}</span>
+<span class="p">}</span>
+</pre></div>
+
+
+<p>The new section is the <code>config</code> section. This provides the application
+configuration (about which you can read more in the <a href="../embedding/appconfig.html">Embedder's Guide</a>).</p>
+<p>The <code>objects</code> part of the config is telling Bespin to create a "global"
+(global within Bespin) object called <code>toolbar</code>. Bespin will look for
+a factory called <code>tutorialtoolbar</code>, which happens to be what we defined
+in the <code>package.json</code> file.</p>
+<p>The <code>gui</code> part of the config is telling Bespin to toss the component
+(object) that we created with the name <code>toolbar</code> into the "north" part
+of the interface. Bespin uses a simple "border layout" with north, south,
+east, west and center locations. So, our toolbar should appear at the top
+of the page.</p>
+<p>Refresh your browser, and you should see our Toolbar! appear at the top.
+<em>If it appears at the bottom, you've witnessed the bug mentioned in the
+introduction.</em></p>
+<h2>CSS3 Flexible Box Model (an aside)</h2>
+<p>CSS3 includes a module called the Flexible Box Model (sometimes called flexbox),
+which Paul Rouget did a great job of introducing
+<a href="http://hacks.mozilla.org/2010/04/the-css-3-flexible-box-model/">in this Mozilla Hacks article</a>. </p>
+<p>Traditionally, HTML+CSS have been quite nice for laying out documents
+but not so great for laying out user interfaces. Flexbox
+makes laying out UI a far easier process.</p>
+<p>Bespin uses flexbox to create the border layout. When you declare that a GUI
+component belongs in the "north", all Bespin has to do is add the "north"
+class to the element, and it pops into the right place.</p>
+<p>Flexbox would also be a great way to create a toolbar, but we're not
+going to go that far in this tutorial.</p>
+<p>By using flexbox, we let the browser do all of the layout which is generally
+faster and smoother than JavaScript-based layouts.</p>
+<h2>Making Our Toolbar Pluggable</h2>
+<p>One of Bespin's main features is that it is customizable and extendable.
+While it's certainly possible to make a static toolbar with a certain
+collection of functions, it's a lot more interesting to create a toolbar
+that is itself pluggable. Plus, that's part of the point of our tutorial.</p>
+<p>We'll start by defining an extension point of our own in <code>package.json</code>.
+Add this as another item in the <code>provides</code> list in <code>package.json</code>:</p>
+<div class="codehilite"><pre><span class="p">{</span>
+ <span class="s2">&quot;ep&quot;</span><span class="o">:</span> <span class="s2">&quot;extensionpoint&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;name&quot;</span><span class="o">:</span> <span class="s2">&quot;tutorialtoolbaritem&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;description&quot;</span><span class="o">:</span> <span class="s2">&quot;Toolbar item views&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;params&quot;</span><span class="o">:</span> <span class="p">[</span>
+ <span class="p">{</span>
+ <span class="s2">&quot;name&quot;</span><span class="o">:</span> <span class="s2">&quot;name&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;description&quot;</span><span class="o">:</span> <span class="s2">&quot;name of this toolbar item&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;type&quot;</span><span class="o">:</span> <span class="s2">&quot;string&quot;</span>
+ <span class="p">},</span>
+ <span class="p">{</span>
+ <span class="s2">&quot;name&quot;</span><span class="o">:</span> <span class="s2">&quot;pointer&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;description&quot;</span><span class="o">:</span> <span class="s2">&quot;pointer to a component that can be instantiated with new and has an element defined on it.&quot;</span>
+ <span class="p">}</span>
+ <span class="p">]</span>
+<span class="p">}</span>
+</pre></div>
+
+
+<p>Extension points themselves are defined via the <code>extensionpoint</code> extension
+point. Seems a bit circular, but it works. We're creating an extension point
+called <code>tutorialtoolbaritem</code>. Bespin is designed to be introspectable,
+so we provide some documentation about the extension point via the <code>description</code>
+and <code>params</code> properties.</p>
+<p>We're going to make <code>tutorialtoolbaritem</code>s look a lot like Bespin's GUI components
+(an object with an <code>element</code> property).</p>
+<p>Now, we need to make our toolbar go out and find the registered <code>tutorialtoolbaritem</code>s.
+We'll change <code>index.js</code> to look like this:</p>
+<div class="codehilite"><pre><span class="kd">var</span> <span class="nx">catalog</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s2">&quot;bespin:plugins&quot;</span><span class="p">).</span><span class="nx">catalog</span><span class="p">;</span>
+
+<span class="nx">exports</span><span class="p">.</span><span class="nx">ToolbarView</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+ <span class="kd">var</span> <span class="nx">elem</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s2">&quot;menu&quot;</span><span class="p">);</span>
+ <span class="nx">elem</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">&#39;class&#39;</span><span class="p">,</span> <span class="s2">&quot;tutorial-toolbar&quot;</span><span class="p">);</span>
+ <span class="nx">elem</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">&#39;type&#39;</span><span class="p">,</span> <span class="s2">&quot;toolbar&quot;</span><span class="p">);</span>
+ <span class="k">this</span><span class="p">.</span><span class="nx">element</span> <span class="o">=</span> <span class="nx">elem</span><span class="p">;</span>
+
+ <span class="k">this</span><span class="p">.</span><span class="nx">_items</span> <span class="o">=</span> <span class="p">[];</span>
+
+ <span class="kd">var</span> <span class="nx">extensions</span> <span class="o">=</span> <span class="nx">catalog</span><span class="p">.</span><span class="nx">getExtensions</span><span class="p">(</span><span class="s1">&#39;tutorialtoolbaritem&#39;</span><span class="p">);</span>
+ <span class="kd">var</span> <span class="nx">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
+ <span class="nx">extensions</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">ext</span><span class="p">)</span> <span class="p">{</span>
+ <span class="nx">ext</span><span class="p">.</span><span class="nx">load</span><span class="p">().</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">item</span><span class="p">)</span> <span class="p">{</span>
+ <span class="nx">item</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">item</span><span class="p">();</span>
+ <span class="nx">self</span><span class="p">.</span><span class="nx">_items</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">item</span><span class="p">);</span>
+ <span class="nx">elem</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">item</span><span class="p">.</span><span class="nx">element</span><span class="p">);</span>
+ <span class="p">});</span>
+ <span class="p">});</span>
+<span class="p">};</span>
+</pre></div>
+
+
+<p>The first thing we're going to do is change the element we're creating into
+an <a href="http://www.w3.org/TR/html5/interactive-elements.html#menus">HTML5 menu element</a>.
+By giving it a type of <code>toolbar</code>, we're letting the browser know that we're
+creating a toolbar. Right now, the browsers don't render the toolbar in any
+special way, but we can use CSS to render the toolbar however we wish.</p>
+<p>Next, we'll make a list to keep track of the items we find. Speaking of finding
+the items, we need to talk to the plugin catalog about that. In the first line
+of the file, we imported the catalog. Now, we call getExtensions which will
+return all of the <code>tutorialtoolbaritem</code>s.</p>
+<p>We use <code>var self = this</code> because we've got some nested callbacks and that's
+a bit nicer to look at than binding each function individually. Then, we loop
+through the list of extensions and call <code>load</code> on each one.</p>
+<p>The <code>load</code> function returns a <em>Promise</em>. Promises provide a convenient way
+to manage callbacks for asynchronous behavior. For our purposes here, the
+only difference between a Promise and a normal callback function is that
+we don't pass the callback directly to <code>load</code>. Instead, we call <code>then</code>
+on the promise and pass the callback to that.</p>
+<p>Back in our metadata for the <code>tutorialtoolbaritem</code> extension point, we defined the
+<code>pointer</code> property as a <em>pointer to a component that can be instantiated with
+new and has an element defined on it.</em> So, when we <code>load</code> the extension, that's
+what we're going to get back. With the tutorialtoolbar item in hand, we can
+call <code>new</code> on it, add that new instance to our items list and then add
+the instance's element to our toolbar.</p>
+<p>And, with that, we have created a dynamically extendable toolbar.</p>
+<h2>Adding Some Items</h2>
+<p>Of course, if we reload our Bespin, the toolbar will be rather boring. We
+haven't added any toolbar items!</p>
+<p>With the infrastructure that we put in place in the last section, we can
+create <code>tutorialtoolbaritem</code>s in any plugin. For convenience, we'll just
+add a couple of items in the tutorialtoolbar plugin.</p>
+<p>We'll make a new module (file) for them in the <code>tutorialtoolbar</code> directory
+called <code>items.js</code>. At this stage, we're not going to make our toolbar items
+<em>do</em> anything, but we just want to have something to display. Here is
+our <code>items.js</code> file:</p>
+<div class="codehilite"><pre><span class="nx">exports</span><span class="p">.</span><span class="nx">Logo</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+ <span class="kd">var</span> <span class="nx">li</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">&#39;li&#39;</span><span class="p">);</span>
+ <span class="nx">li</span><span class="p">.</span><span class="nx">innerHTML</span> <span class="o">=</span> <span class="s2">&quot;Logo here&quot;</span><span class="p">;</span>
+ <span class="k">this</span><span class="p">.</span><span class="nx">element</span> <span class="o">=</span> <span class="nx">li</span><span class="p">;</span>
+<span class="p">};</span>
+
+<span class="nx">exports</span><span class="p">.</span><span class="nx">OpenFileIndicator</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+ <span class="kd">var</span> <span class="nx">li</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">&#39;li&#39;</span><span class="p">);</span>
+ <span class="nx">li</span><span class="p">.</span><span class="nx">innerHTML</span> <span class="o">=</span> <span class="s2">&quot;SampleProject &amp;mdash; readme.txt&quot;</span><span class="p">;</span>
+ <span class="k">this</span><span class="p">.</span><span class="nx">element</span> <span class="o">=</span> <span class="nx">li</span><span class="p">;</span>
+<span class="p">};</span>
+
+<span class="nx">exports</span><span class="p">.</span><span class="nx">Save</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+ <span class="kd">var</span> <span class="nx">li</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">&#39;li&#39;</span><span class="p">);</span>
+ <span class="nx">li</span><span class="p">.</span><span class="nx">innerHTML</span> <span class="o">=</span> <span class="s2">&quot;Save&quot;</span><span class="p">;</span>
+ <span class="k">this</span><span class="p">.</span><span class="nx">element</span> <span class="o">=</span> <span class="nx">li</span><span class="p">;</span>
+<span class="p">};</span>
+
+<span class="nx">exports</span><span class="p">.</span><span class="nx">PositionIndicator</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+ <span class="kd">var</span> <span class="nx">li</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">&#39;li&#39;</span><span class="p">);</span>
+ <span class="nx">li</span><span class="p">.</span><span class="nx">innerHTML</span> <span class="o">=</span> <span class="s2">&quot;Row 0, Column 0&quot;</span><span class="p">;</span>
+ <span class="k">this</span><span class="p">.</span><span class="nx">element</span> <span class="o">=</span> <span class="nx">li</span><span class="p">;</span>
+<span class="p">};</span>
+</pre></div>
+
+
+<p>As you can see, each one of these functions does nothing but create an
+<code>li</code> element (as per the HTML5 spec for menus) and add that element
+to the instance on the <code>element</code> property.</p>
+<p>One more thing to do before we can see our toolbar. We need to register
+the extensions for our <code>tutorialtoolbar</code> extension point. Back in
+<code>package.json</code>, we're going to add these four more items to our
+<code>provides</code> property:</p>
+<div class="codehilite"><pre><span class="p">{</span>
+ <span class="s2">&quot;ep&quot;</span><span class="o">:</span> <span class="s2">&quot;tutorialtoolbaritem&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;name&quot;</span><span class="o">:</span> <span class="s2">&quot;logo&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;pointer&quot;</span><span class="o">:</span> <span class="s2">&quot;items#Logo&quot;</span>
+<span class="p">},</span>
+<span class="p">{</span>
+ <span class="s2">&quot;ep&quot;</span><span class="o">:</span> <span class="s2">&quot;tutorialtoolbaritem&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;name&quot;</span><span class="o">:</span> <span class="s2">&quot;openfileindicator&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;pointer&quot;</span><span class="o">:</span> <span class="s2">&quot;items#OpenFileIndicator&quot;</span>
+<span class="p">},</span>
+<span class="p">{</span>
+ <span class="s2">&quot;ep&quot;</span><span class="o">:</span> <span class="s2">&quot;tutorialtoolbaritem&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;name&quot;</span><span class="o">:</span> <span class="s2">&quot;save&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;pointer&quot;</span><span class="o">:</span> <span class="s2">&quot;items#Save&quot;</span>
+<span class="p">},</span>
+<span class="p">{</span>
+ <span class="s2">&quot;ep&quot;</span><span class="o">:</span> <span class="s2">&quot;tutorialtoolbaritem&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;name&quot;</span><span class="o">:</span> <span class="s2">&quot;positionindicator&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;pointer&quot;</span><span class="o">:</span> <span class="s2">&quot;items#PositionIndicator&quot;</span>
+<span class="p">}</span>
+</pre></div>
+
+
+<p>You can see that each one of these refers to the <code>items</code> module in the
+pointer, since that's where we put these items.</p>
+<p>For reference, here's the complete <code>package.json</code> file at this stage:</p>
+<div class="codehilite"><pre><span class="p">{</span>
+ <span class="s2">&quot;provides&quot;</span><span class="o">:</span> <span class="p">[</span>
+ <span class="p">{</span>
+ <span class="s2">&quot;ep&quot;</span><span class="o">:</span> <span class="s2">&quot;factory&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;name&quot;</span><span class="o">:</span> <span class="s2">&quot;tutorialtoolbar&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;action&quot;</span><span class="o">:</span> <span class="s2">&quot;new&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;pointer&quot;</span><span class="o">:</span> <span class="s2">&quot;#ToolbarView&quot;</span>
+ <span class="p">},</span>
+ <span class="p">{</span>
+ <span class="s2">&quot;ep&quot;</span><span class="o">:</span> <span class="s2">&quot;extensionpoint&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;name&quot;</span><span class="o">:</span> <span class="s2">&quot;toolbaritem&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;description&quot;</span><span class="o">:</span> <span class="s2">&quot;Toolbar item views&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;params&quot;</span><span class="o">:</span> <span class="p">[</span>
+ <span class="p">{</span>
+ <span class="s2">&quot;name&quot;</span><span class="o">:</span> <span class="s2">&quot;name&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;description&quot;</span><span class="o">:</span> <span class="s2">&quot;name of this toolbar item&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;type&quot;</span><span class="o">:</span> <span class="s2">&quot;string&quot;</span>
+ <span class="p">},</span>
+ <span class="p">{</span>
+ <span class="s2">&quot;name&quot;</span><span class="o">:</span> <span class="s2">&quot;pointer&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;description&quot;</span><span class="o">:</span> <span class="s2">&quot;pointer to a component that can be instantiated with new and has an element defined on it.&quot;</span>
+ <span class="p">}</span>
+ <span class="p">]</span>
+ <span class="p">},</span>
+ <span class="p">{</span>
+ <span class="s2">&quot;ep&quot;</span><span class="o">:</span> <span class="s2">&quot;tutorialtoolbaritem&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;name&quot;</span><span class="o">:</span> <span class="s2">&quot;logo&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;pointer&quot;</span><span class="o">:</span> <span class="s2">&quot;items#Logo&quot;</span>
+ <span class="p">},</span>
+ <span class="p">{</span>
+ <span class="s2">&quot;ep&quot;</span><span class="o">:</span> <span class="s2">&quot;tutorialtoolbaritem&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;name&quot;</span><span class="o">:</span> <span class="s2">&quot;openfileindicator&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;pointer&quot;</span><span class="o">:</span> <span class="s2">&quot;items#OpenFileIndicator&quot;</span>
+ <span class="p">},</span>
+ <span class="p">{</span>
+ <span class="s2">&quot;ep&quot;</span><span class="o">:</span> <span class="s2">&quot;tutorialtoolbaritem&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;name&quot;</span><span class="o">:</span> <span class="s2">&quot;save&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;pointer&quot;</span><span class="o">:</span> <span class="s2">&quot;items#Save&quot;</span>
+ <span class="p">},</span>
+ <span class="p">{</span>
+ <span class="s2">&quot;ep&quot;</span><span class="o">:</span> <span class="s2">&quot;tutorialtoolbaritem&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;name&quot;</span><span class="o">:</span> <span class="s2">&quot;positionindicator&quot;</span><span class="p">,</span>
+ <span class="s2">&quot;pointer&quot;</span><span class="o">:</span> <span class="s2">&quot;items#PositionIndicator&quot;</span>
+ <span class="p">}</span>
+ <span class="p">]</span>
+<span class="p">}</span>
+</pre></div>
+
+
+<p>With that, we've done everything we need to do to see our toolbar. Let's
+reload the page. You should see something that looks like this:</p>
+<p><img alt="Toolbar displayed as list" src="ToolbarAsList.png"></p>
+<p>It worked! It has our items in it! Doesn't look much like a toolbar, though,
+does it?</p>
+<h2>Styling Your Plugins</h2>
+<p>To make our toolbar look like a toolbar, we need to add some styles. In order
+to support themes properly, Bespin uses <a href="http://lesscss.org">LESS</a>, which is
+an extended CSS syntax.</p>
+<p>In the <code>tutorialtoolbar</code> directory, create a <code>resources</code> directory. In there,
+create a file called <code>toolbar.less</code>. We need to tell Bespin's theme manager
+about this file, so we need to add one more thing to the <code>provides</code> property