Skip to content
Browse files

Bug 673187 - Remove docs server, first part; r=warner

  • Loading branch information...
1 parent da3c144 commit 6d19ec4b68fd651da5b0163bdc62bc5d6b418f33 @wbamberg wbamberg committed Sep 12, 2011
Showing with 1,018 additions and 247 deletions.
  1. +5 −1 .gitignore
  2. 0 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/about.md
  3. 0 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/annotator/annotator.md
  4. +2 −2 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/annotator/creating.md
  5. +2 −2 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/annotator/displaying.md
  6. +1 −1 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/annotator/overview.md
  7. +1 −1 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/annotator/storing.md
  8. +3 −3 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/annotator/widget.md
  9. 0 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/api-idioms.md
  10. 0 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/api-intro.md
  11. +6 −6 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/api-modules.md
  12. +18 −2 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/cfx-tool.md
  13. +2 −2 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/commonjs.md
  14. 0 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/console.md
  15. 0 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/content-scripts/access.md
  16. 0 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/content-scripts/loading.md
  17. 0 ...ic-files/md/dev-guide → doc/dev-guide-source}/addon-development/content-scripts/reddit-example.md
  18. +179 −0 doc/dev-guide-source/addon-development/content-scripts/using-port.md
  19. 0 ...files/md/dev-guide → doc/dev-guide-source}/addon-development/content-scripts/using-postmessage.md
  20. 0 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/events.md
  21. 0 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/getting-started.md
  22. 0 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/guides.md
  23. 0 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/implementing-reusable-module.md
  24. +2 −2 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/implementing-simple-addon.md
  25. +1 −1 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/installation.md
  26. 0 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/module-search.md
  27. 0 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/package-spec.md
  28. 0 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/program-id.md
  29. 0 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/reference.md
  30. 0 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/troubleshooting.md
  31. 0 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/tutorials.md
  32. 0 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/two-types-of-scripts.md
  33. +1 −1 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/web-content.md
  34. 0 {static-files/md/dev-guide → doc/dev-guide-source}/appendices/credits.md
  35. 0 {static-files/md/dev-guide → doc/dev-guide-source}/appendices/glossary.md
  36. 0 {static-files/md/dev-guide → doc/dev-guide-source}/module-development/about.md
  37. 0 {static-files/md/dev-guide → doc/dev-guide-source}/module-development/best-practices.md
  38. 0 {static-files/md/dev-guide → doc/dev-guide-source}/module-development/chrome.md
  39. +1 −1 {static-files/md/dev-guide → doc/dev-guide-source}/module-development/e10s.md
  40. 0 {static-files/md/dev-guide → doc/dev-guide-source}/module-development/globals.md
  41. 0 {static-files/md/dev-guide → doc/dev-guide-source}/module-development/guides.md
  42. 0 {static-files/md/dev-guide → doc/dev-guide-source}/module-development/reference.md
  43. 0 {static-files/md/dev-guide → doc/dev-guide-source}/module-development/tutorials.md
  44. 0 {static-files/md/dev-guide → doc/dev-guide-source}/module-development/xpi.md
  45. 0 {static-files/md/dev-guide → doc/dev-guide-source}/welcome.md
  46. +15 −15 { → doc}/static-files/base.html
  47. 0 { → doc}/static-files/css/api-reference.css
  48. 0 { → doc}/static-files/css/base.css
  49. 0 { → doc}/static-files/css/footer.css
  50. 0 { → doc}/static-files/css/header.css
  51. 0 { → doc}/static-files/css/sdk-docs.css
  52. 0 { → doc}/static-files/js/jquery.js
  53. +0 −24 { → doc}/static-files/js/main.js
  54. +175 −0 doc/static-files/md/dev-guide/addon-development/content-scripts/access.md
  55. +60 −0 doc/static-files/md/dev-guide/addon-development/content-scripts/loading.md
  56. +67 −0 doc/static-files/md/dev-guide/addon-development/content-scripts/reddit-example.md
  57. 0 { → doc}/static-files/md/dev-guide/addon-development/content-scripts/using-port.md
  58. +136 −0 doc/static-files/md/dev-guide/addon-development/content-scripts/using-postmessage.md
  59. 0 { → doc}/static-files/media/annotator/annotation-list.png
  60. 0 { → doc}/static-files/media/annotator/annotation-panel.png
  61. 0 { → doc}/static-files/media/annotator/annotator-design.png
  62. 0 { → doc}/static-files/media/annotator/editor-panel.png
  63. 0 { → doc}/static-files/media/annotator/highlight.png
  64. 0 { → doc}/static-files/media/annotator/matcher.png
  65. 0 { → doc}/static-files/media/annotator/pencil-off.png
  66. 0 { → doc}/static-files/media/annotator/pencil-on.png
  67. 0 { → doc}/static-files/media/annotator/widget-icon.png
  68. 0 { → doc}/static-files/media/bg-footer.png
  69. 0 { → doc}/static-files/media/bg-header.png
  70. 0 { → doc}/static-files/media/commonjs-modules.jpg
  71. 0 { → doc}/static-files/media/commonjs-translator.jpg
  72. 0 { → doc}/static-files/media/content-scripting-events.png
  73. 0 { → doc}/static-files/media/content-scripting-overview.png
  74. 0 { → doc}/static-files/media/favicon.png
  75. 0 { → doc}/static-files/media/firefox-32.png
  76. 0 { → doc}/static-files/media/firefox-logo.png
  77. 0 { → doc}/static-files/media/footer-logo-med.png
  78. 0 { → doc}/static-files/media/mozilla-tab.png
  79. 0 { → doc}/static-files/media/multiple-workers.jpg
  80. 0 { → doc}/static-files/media/screenshots/default-panel-osx.png
  81. 0 { → doc}/static-files/media/screenshots/default-panel-ubuntu.png
  82. 0 { → doc}/static-files/media/screenshots/default-panel-windows.png
  83. 0 { → doc}/static-files/media/screenshots/modules/context-menu-image-osx.png
  84. 0 { → doc}/static-files/media/screenshots/modules/notification-growl-osx.png
  85. 0 { → doc}/static-files/media/screenshots/modules/panel-tabs-osx.png
  86. 0 { → doc}/static-files/media/screenshots/modules/widget-content-osx.png
  87. 0 { → doc}/static-files/media/screenshots/modules/widget-icon-osx.png
  88. 0 { → doc}/static-files/media/screenshots/modules/widget-panel-osx.png
  89. 0 { → doc}/static-files/media/screenshots/translator/context-menu-osx.png
  90. 0 { → doc}/static-files/media/screenshots/translator/translated-osx.png
  91. 0 { → doc}/static-files/media/screenshots/widget-panel-clock.png
  92. 0 { → doc}/static-files/media/twitter-widget.png
  93. 0 { → doc}/static-files/syntaxhighlighter/MIT-LICENSE
  94. 0 { → doc}/static-files/syntaxhighlighter/scripts/shBrushCss.js
  95. 0 { → doc}/static-files/syntaxhighlighter/scripts/shBrushJScript.js
  96. 0 { → doc}/static-files/syntaxhighlighter/scripts/shBrushXml.js
  97. 0 { → doc}/static-files/syntaxhighlighter/scripts/shCore.js
  98. 0 { → doc}/static-files/syntaxhighlighter/styles/shCore.css
  99. 0 { → doc}/static-files/syntaxhighlighter/styles/shThemeDefault.css
  100. +1 −1 packages/addon-kit/docs/page-mod.md
  101. +3 −3 packages/addon-kit/docs/panel.md
  102. +1 −1 packages/addon-kit/docs/widget.md
  103. +9 −15 python-lib/cuddlefish/__init__.py
  104. 0 python-lib/cuddlefish/docs/__init__.py
  105. 0 python-lib/cuddlefish/{ → docs}/apiparser.py
  106. 0 python-lib/cuddlefish/{ → docs}/apirenderer.py
  107. +224 −0 python-lib/cuddlefish/docs/generate.py
  108. +3 −3 python-lib/cuddlefish/{ → docs}/webdocs.py
  109. +4 −115 python-lib/cuddlefish/server.py
  110. +1 −1 python-lib/cuddlefish/tests/__init__.py
  111. 0 python-lib/cuddlefish/tests/static-files/{static-files/md/dev-guide → doc/dev-guide-source}/no_h1.md
  112. 0 ...n-lib/cuddlefish/tests/static-files/{static-files/md/dev-guide → doc/dev-guide-source}/welcome.md
  113. 0 python-lib/cuddlefish/tests/static-files/{ → doc}/static-files/base.html
  114. 0 python-lib/cuddlefish/tests/static-files/{ → doc}/static-files/index.html
  115. +1 −0 python-lib/cuddlefish/tests/static-files/doc/status.md5
  116. +1 −1 python-lib/cuddlefish/tests/test_apiparser.py
  117. +2 −2 python-lib/cuddlefish/tests/test_apirenderer.py
  118. +87 −0 python-lib/cuddlefish/tests/test_generate.py
  119. +1 −38 python-lib/cuddlefish/tests/test_server.py
  120. +3 −3 python-lib/cuddlefish/tests/test_webdocs.py
View
6 .gitignore
@@ -3,7 +3,11 @@ python-lib/cuddlefish/app-extension/components/jetpack.xpt
testdocs.tgz
jetpack-sdk-docs.tgz
.test_tmp/
-jetpack-sdk-docs/
+doc/dev-guide/
+doc/index.html
+doc/packages/
+doc/status.md5
+
# If you want to add other files here, like *.pyc and *.DS_Store,
# please add them to a global git ignore file.
View
0 ...s/md/dev-guide/addon-development/about.md → ...v-guide-source/addon-development/about.md
File renamed without changes.
View
0 .../addon-development/annotator/annotator.md → .../addon-development/annotator/annotator.md
File renamed without changes.
View
4 ...e/addon-development/annotator/creating.md → ...e/addon-development/annotator/creating.md
@@ -170,7 +170,7 @@ overview-amo-review-process/](http://blog.mozilla.com/addons/2011/02/04/overview
You should see the highlight appearing when you move the mouse over certain elements:
<img class="image-center"
-src="media/annotator/highlight.png" alt="Annotator Highlighting">
+src="static-files/media/annotator/highlight.png" alt="Annotator Highlighting">
Click on the highlight and you should see something like this in the console
output:
@@ -323,7 +323,7 @@ element and click the element when it is highlighted. You should see a panel
with a text area for a note:
<img class="image-center"
-src="media/annotator/editor-panel.png" alt="Annotator Editor Panel">
+src="static-files/media/annotator/editor-panel.png" alt="Annotator Editor Panel">
<br>
Enter the note and press the return key: you should see console output like
View
4 ...addon-development/annotator/displaying.md → ...addon-development/annotator/displaying.md
@@ -191,13 +191,13 @@ Execute `cfx run` one last time. Activate the annotator and enter an
annotation. You should see a yellow border around the item you annotated:
<img class="image-center"
-src="media/annotator/matcher.png" alt="Annotator Matcher">
+src="static-files/media/annotator/matcher.png" alt="Annotator Matcher">
<br>
When you move your mouse over the item, the annotation should appear:
<img class="image-center"
-src="media/annotator/annotation-panel.png" alt="Annotation Panel">
+src="static-files/media/annotator/annotation-panel.png" alt="Annotation Panel">
<br>
Obviously this add-on isn't complete yet. It could do with more beautiful
View
2 ...e/addon-development/annotator/overview.md → ...e/addon-development/annotator/overview.md
@@ -10,7 +10,7 @@ We could represent the basic interactions between the `main` module and the
various content scripts like this:
<img class="image-center"
-src="media/annotator/annotator-design.png" alt="Annotator Design">
+src="static-files/media/annotator/annotator-design.png" alt="Annotator Design">
## User Interface ##
View
2 ...de/addon-development/annotator/storing.md → ...ce/addon-development/annotator/storing.md
@@ -233,7 +233,7 @@ Firefox. Activate the add-on, add an annotation, and then right-click the
widget. You should see something like this:
<img class="image-center"
-src="media/annotator/annotation-list.png" alt="Annotation List">
+src="static-files/media/annotator/annotation-list.png" alt="Annotation List">
<br>
<span class="aside">
View
6 ...ide/addon-development/annotator/widget.md → ...rce/addon-development/annotator/widget.md
@@ -46,8 +46,8 @@ Save this in your `data/widget` directory as `widget.js`.
You can copy the widget's icons from here:
-<img style="margin-left:40px; margin-right:20px;" src="media/annotator/pencil-on.png" alt="Active Annotator">
-<img style="margin-left:20px; margin-right:20px;" src="media/annotator/pencil-off.png" alt="Inactive Annotator">
+<img style="margin-left:40px; margin-right:20px;" src="static-files/media/annotator/pencil-on.png" alt="Active Annotator">
+<img style="margin-left:20px; margin-right:20px;" src="static-files/media/annotator/pencil-off.png" alt="Inactive Annotator">
(Or make your own if you're feeling creative.) Save them in your `data/widget` directory.
@@ -100,7 +100,7 @@ Now from the `annotator` directory type `cfx run`. You should see the widget
in the add-on bar:
<div align="center">
-<img src="media/annotator/widget-icon.png" alt="Widget Icon">
+<img src="static-files/media/annotator/widget-icon.png" alt="Widget Icon">
</div>
<br>
View
0 ...dev-guide/addon-development/api-idioms.md → ...de-source/addon-development/api-idioms.md
File renamed without changes.
View
0 .../dev-guide/addon-development/api-intro.md → ...ide-source/addon-development/api-intro.md
File renamed without changes.
View
12 ...ev-guide/addon-development/api-modules.md → ...e-source/addon-development/api-modules.md
@@ -22,7 +22,7 @@ You can build or load the content locally or load it from a remote server.
The screenshot below shows a panel whose content is built from the list of
currently open tabs:
-<img class="image-center" src="media/screenshots/modules/panel-tabs-osx.png"
+<img class="image-center" src="static-files/media/screenshots/modules/panel-tabs-osx.png"
alt="List open tabs panel">
<br>
@@ -40,7 +40,7 @@ Widgets are generally used in one of two different contexts:
the time in a selected time zone or the weather. The screenshot below shows a
widget that displays the time in the selected city:
-<img class="image-center" src="media/screenshots/modules/widget-content-osx.png"
+<img class="image-center" src="static-files/media/screenshots/modules/widget-content-osx.png"
alt="Mozilla widget content">
<br>
@@ -49,15 +49,15 @@ interface. For example, a widget might display only an icon, but open a
settings dialog when the user clicks it. The widget below displays only the
Mozilla icon:
-<img class="image-center" src="media/screenshots/modules/widget-icon-osx.png"
+<img class="image-center" src="static-files/media/screenshots/modules/widget-icon-osx.png"
alt="Mozilla widget icon">
<br>
To simplify your code in the latter case, you can assign a panel object to
your widget. Then when the user clicks the widget, the widget will display
the panel anchored to the widget:
-<img class="image-center" src="media/screenshots/modules/widget-panel-osx.png"
+<img class="image-center" src="static-files/media/screenshots/modules/widget-panel-osx.png"
alt="Panel anchored to widget">
<br>
@@ -73,7 +73,7 @@ is selected) or define your own contexts using scripts.
In the screenshot below an add-on has added a new submenu to the context menu
associated with `img` elements:
-<img class="image-center" src="media/screenshots/modules/context-menu-image-osx.png"
+<img class="image-center" src="static-files/media/screenshots/modules/context-menu-image-osx.png"
alt="Context-menu">
<br>
@@ -86,7 +86,7 @@ OS X and Windows, libnotify on Linux), so the notification will look slightly
different on different platforms. On Mac OS X a notification will look
something like this:
-<img class="image-center" src="media/screenshots/modules/notification-growl-osx.png"
+<img class="image-center" src="static-files/media/screenshots/modules/notification-growl-osx.png"
alt="Growl notification">
<br>
View
20 ...d/dev-guide/addon-development/cfx-tool.md → ...uide-source/addon-development/cfx-tool.md
@@ -23,8 +23,24 @@ applicable to a subset of the commands.
### cfx docs ###
-This command launches an HTTP server on the localhost to view web-based
-documentation in a new Firefox window.
+This command displays the documentation for the SDK. The documentation is
+shipped with the SDK in [Markdown](http://daringfireball.net/projects/markdown/)
+format. The first time this command is executed, and any time after the
+Markdown files on disk have changed, `cfx docs` will generate a set of HTML
+pages from them and launch a web browser to display them. If the Markdown files
+haven't changed, `cfx docs` just launches a browser initialized to the set of
+generated pages.
+
+To regenerate the documentation associated with a single file, you can
+specify the file as an argument. For example:
+
+<pre>
+ cfx docs doc/dev-guide-source/addon-development/cfx-tool.md
+</pre>
+
+This command will regenerate only the HTML page you're reading.
+This is useful if you're iteratively editing a single file, and don't want to wait for cfx to
+regenerate the complete documentation tree.
### cfx init ####
Create a new directory, change into it, and run `cfx init`.
View
4 ...d/dev-guide/addon-development/commonjs.md → ...uide-source/addon-development/commonjs.md
@@ -19,7 +19,7 @@ module wants to make available to other modules
object of another module. Your translator add-on uses `require` to import the
SDK modules it uses.
-![CommonJS modules](media/commonjs-modules.jpg)
+![CommonJS modules](static-files/media/commonjs-modules.jpg)
The SDK
[freezes](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/freeze)
@@ -62,7 +62,7 @@ soon as Firefox has enabled the add-on.
So in terms of CommonJS objects the translator consists of a package that
contains a single module called `main`, and which imports three SDK modules:
-![CommonJS translator](media/commonjs-translator.jpg)
+![CommonJS translator](static-files/media/commonjs-translator.jpg)
Because an add-on is a CommonJS package it's possible to include more than one
module in an add-on, and to make your modules available to any code that want
View
0 ...md/dev-guide/addon-development/console.md → ...guide-source/addon-development/console.md
File renamed without changes.
View
0 ...don-development/content-scripts/access.md → ...don-development/content-scripts/access.md
File renamed without changes.
View
0 ...on-development/content-scripts/loading.md → ...on-development/content-scripts/loading.md
File renamed without changes.
View
0 ...lopment/content-scripts/reddit-example.md → ...lopment/content-scripts/reddit-example.md
File renamed without changes.
View
179 doc/dev-guide-source/addon-development/content-scripts/using-port.md
@@ -0,0 +1,179 @@
+
+# Communicating using "port" #
+
+To enable add-on scripts and content scripts to communicate with each other,
+each end of the conversation has access to a `port` object which defines two
+functions:
+
+**`emit()`** is used to emit an event. It may be called with any number of
+parameters, but is most likely to be called with a name for the event and
+an optional payload. The payload can be any value that is
+<a href = "dev-guide/addon-development/content-scripts/using-port.html#json_serializable">serializable to JSON</a>
+
+ port.emit("myEvent", myEventPayload);
+
+**`on()`** takes two parameters: the name of the event and a function to handle it:
+
+ port.on("myEvent", function handleMyEvent(myEventPayload) {
+ // Handle the event
+ });
+
+Here's simple add-on that sends a message to a content script using `port`:
+
+ var tabs = require("tabs");
+
+ var alertContentScript = "self.port.on('alert', function(message) {" +
+ " window.alert(message);" +
+ "})";
+
+ tabs.on("ready", function(tab) {
+ worker = tab.attach({
+ contentScript: alertContentScript
+ });
+ worker.port.emit("alert", "Message from the add-on");
+ });
+
+ tabs.open("http://www.mozilla.org");
+
+We could depict the interface between add-on code and content script code like
+this:
+
+<img class="image-center" src="static-files/media/content-scripting-events.png"
+alt="Content script events">
+
+Events are asynchronous: that is, the sender does not wait for a reply from
+the recipient but just emits the event and continues processing.
+
+## Accessing `port` in the Content Script ##
+
+<span class="aside">Note that the global `self` object is completely
+different from the [`self` module](packages/addon-kit/docs/self.html), which
+provides an API for an add-on to access its data files and ID.</span>
+
+In the content script the `port` object is available as a property of the
+global `self` object. Thus, to emit an event from a content script:
+
+ self.port.emit("myContentScriptEvent", myContentScriptEventPayload);
+
+To receive an event from the add-on code:
+
+ self.port.on("myAddonEvent", function(myAddonEventPayload) {
+ // Handle the event
+ });
+
+Compare this to the technique used to receive _built-in_ events in the
+content script. For example, to receive the `context` event in a content script
+associated with a [context menu](packages/addon-kit/docs/context-menu.html)
+object, you would call the `on` function attached to the global `self` object:
+
+ self.on("context", function() {
+ // Handle the event
+ });
+
+So the `port` property is essentially used here as a namespace for
+user-defined events.
+
+## Accessing `port` in the Add-on Script ##
+
+In the add-on code, the channel of communication between the add-on and a
+particular content script context is encapsulated by the `worker` object. Thus
+the `port` object for communicating with a content script is a property of the
+corresponding `worker` object.
+
+However, the worker is not exposed to add-on code in quite the same way
+in all modules. The `panel` and `page-worker` objects integrate the
+worker API directly. So to receive events from a content script associated
+with a panel you use `panel.port.on()`:
+
+ var panel = require("panel").Panel({
+ contentScript: "self.port.emit('showing', 'panel is showing');"
+ });
+
+ panel.port.on("showing", function(text) {
+ console.log(text);
+ });
+
+ panel.show();
+
+Conversely, to emit user-defined events from your add-on you can just call
+`panel.port.emit()`:
+
+ var panel = require("panel").Panel({
+ contentScript: "self.port.on('alert', function(text) {" +
+ " console.log(text);" +
+ "});"
+ });
+
+ panel.show();
+ panel.port.emit("alert", "panel is showing");
+
+The `panel` and `page-worker` objects only host a single page at a time,
+so each distinct page object only needs a single channel of communication
+to its content scripts. But some modules, such as `page-mod`, might need to
+handle multiple pages, each with its own context in which the content scripts
+are executing, so it needs a separate channel (worker) for each page.
+
+So `page-mod` does not integrate the worker API directly: instead, each time a
+content script is attached to a page, the worker associated with the page is
+supplied to the page-mod in its `onAttach` function. By supplying a target for
+this function in the page-mod's constructor you can register to receive
+events from the content script, and take a reference to the worker so as to
+emit events to it.
+
+ var pageModScript = "window.addEventListener('click', function(event) {" +
+ " self.port.emit('click', event.target.toString());" +
+ " event.stopPropagation();" +
+ " event.preventDefault();" +
+ "}, false);" +
+ "self.port.on('warning', function(message) {" +
+ "window.alert(message);" +
+ "});"
+
+ var pageMod = require('page-mod').PageMod({
+ include: ['*'],
+ contentScript: pageModScript,
+ onAttach: function(worker) {
+ worker.port.on('click', function(html) {
+ worker.port.emit('warning', 'Do not click this again');
+ });
+ }
+ });
+
+In the add-on above there are two user-defined events:
+
+* `click` is sent from the page-mod to the add-on, when the user clicks an
+element in the page
+* `warning` sends a silly string back to the page-mod
+
+## <a name="json_serializable">JSON-Serializable Values</a> ##
+
+The payload for an event can be any JSON-serializable value. When events are
+sent their payloads are automatically serialized, and when events are received
+their payloads are automatically deserialized, so you don't need to worry
+about serialization.
+
+However, you _do_ have to ensure that the payload can be serialized to JSON.
+This means that it needs to be a string, number, boolean, null, array of
+JSON-serializable values, or an object whose property values are themselves
+JSON-serializable. This means you can't send functions, and if the object
+contains methods they won't be encoded.
+
+For example, to include an array of strings in the payload:
+
+ var pageModScript = "self.port.emit('loaded'," +
+ " [" +
+ " document.location.toString()," +
+ " document.title" +
+ " ]" +
+ ");"
+
+ var pageMod = require('page-mod').PageMod({
+ include: ['*'],
+ contentScript: pageModScript,
+ onAttach: function(worker) {
+ worker.port.on('loaded', function(pageInfo) {
+ console.log(pageInfo[0]);
+ console.log(pageInfo[1]);
+ });
+ }
+ });
View
0 ...ment/content-scripts/using-postmessage.md → ...ment/content-scripts/using-postmessage.md
File renamed without changes.
View
0 .../md/dev-guide/addon-development/events.md → ...-guide-source/addon-development/events.md
File renamed without changes.
View
0 ...uide/addon-development/getting-started.md → ...urce/addon-development/getting-started.md
File renamed without changes.
View
0 .../md/dev-guide/addon-development/guides.md → ...-guide-source/addon-development/guides.md
File renamed without changes.
View
0 ...velopment/implementing-reusable-module.md → ...velopment/implementing-reusable-module.md
File renamed without changes.
View
4 ...-development/implementing-simple-addon.md → ...-development/implementing-simple-addon.md
@@ -250,12 +250,12 @@ page containing some text that is not in English, for example:
Select some text on that page and right-click to activate the context menu.
You should see a new item labeled "Translate Selection":
-![translator context-menu](media/screenshots/translator/context-menu-osx.png)
+![translator context-menu](static-files/media/screenshots/translator/context-menu-osx.png)
Select that item and the text you selected should be replaced with its English
translation:
-![translator context-menu](media/screenshots/translator/translated-osx.png)
+![translator context-menu](static-files/media/screenshots/translator/translated-osx.png)
You will also see output like this appear in your command shell:
View
2 ...v-guide/addon-development/installation.md → ...-source/addon-development/installation.md
@@ -114,7 +114,7 @@ add-on for distribution, view documentation, and run unit tests.
## cfx docs ##
If you're reading these documents online, try running `cfx docs`. This will
-run a self-hosted documentation server and open it in your web browser.
+build the documentation for the SDK and display it in a browser.
## Problems? ##
View
0 ...-guide/addon-development/module-search.md → ...source/addon-development/module-search.md
File renamed without changes.
View
0 ...v-guide/addon-development/package-spec.md → ...-source/addon-development/package-spec.md
File renamed without changes.
View
0 ...dev-guide/addon-development/program-id.md → ...de-source/addon-development/program-id.md
File renamed without changes.
View
0 .../dev-guide/addon-development/reference.md → ...ide-source/addon-development/reference.md
File renamed without changes.
View
0 ...uide/addon-development/troubleshooting.md → ...urce/addon-development/troubleshooting.md
File renamed without changes.
View
0 .../dev-guide/addon-development/tutorials.md → ...ide-source/addon-development/tutorials.md
File renamed without changes.
View
0 ...addon-development/two-types-of-scripts.md → ...addon-development/two-types-of-scripts.md
File renamed without changes.
View
2 ...ev-guide/addon-development/web-content.md → ...e-source/addon-development/web-content.md
@@ -49,7 +49,7 @@ to the event-handling interfaces described in the
The diagram below shows an overview of the main components and their
relationships. The gray fill represents code written by the add-on developer.
-<img class="image-center" src="media/content-scripting-overview.png"
+<img class="image-center" src="static-files/media/content-scripting-overview.png"
alt="Content script events">
This might sound complicated but it doesn't need to be. The following add-on
View
0 ...-files/md/dev-guide/appendices/credits.md → doc/dev-guide-source/appendices/credits.md
File renamed without changes.
View
0 ...files/md/dev-guide/appendices/glossary.md → doc/dev-guide-source/appendices/glossary.md
File renamed without changes.
View
0 .../md/dev-guide/module-development/about.md → ...-guide-source/module-development/about.md
File renamed without changes.
View
0 ...uide/module-development/best-practices.md → ...urce/module-development/best-practices.md
File renamed without changes.
View
0 ...md/dev-guide/module-development/chrome.md → ...guide-source/module-development/chrome.md
File renamed without changes.
View
2 ...s/md/dev-guide/module-development/e10s.md → ...v-guide-source/module-development/e10s.md
@@ -16,7 +16,7 @@ parent chrome process.
## The Big Picture ##
-![Multi-Process Architecture](media/twitter-widget.png)
+![Multi-Process Architecture](static-files/media/twitter-widget.png)
The above diagram is a simplified depiction of what happens when a hypothetical
add-on using the `widget` module is loaded.
View
0 ...d/dev-guide/module-development/globals.md → ...uide-source/module-development/globals.md
File renamed without changes.
View
0 ...md/dev-guide/module-development/guides.md → ...guide-source/module-development/guides.md
File renamed without changes.
View
0 ...dev-guide/module-development/reference.md → ...de-source/module-development/reference.md
File renamed without changes.
View
0 ...dev-guide/module-development/tutorials.md → ...de-source/module-development/tutorials.md
File renamed without changes.
View
0 ...es/md/dev-guide/module-development/xpi.md → ...ev-guide-source/module-development/xpi.md
File renamed without changes.
View
0 static-files/md/dev-guide/welcome.md → doc/dev-guide-source/welcome.md
File renamed without changes.
View
30 static-files/base.html → doc/static-files/base.html
@@ -4,17 +4,17 @@
<head>
<base >
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
- <script type="text/javascript" src="syntaxhighlighter/scripts/shCore.js"></script>
- <script type="text/javascript" src="syntaxhighlighter/scripts/shBrushCss.js"></script>
- <script type="text/javascript" src="syntaxhighlighter/scripts/shBrushXml.js"></script>
- <script type="text/javascript" src="syntaxhighlighter/scripts/shBrushJScript.js"></script>
- <link rel="stylesheet" type="text/css" media="all" href="css/base.css">
- <link rel="stylesheet" type="text/css" media="all" href="css/header.css">
- <link rel="stylesheet" type="text/css" media="all" href="css/footer.css">
- <link rel="stylesheet" type="text/css" media="all" href="css/sdk-docs.css">
- <link rel="stylesheet" type="text/css" media="all" href="css/api-reference.css">
- <link rel="stylesheet" type="text/css" href="syntaxhighlighter/styles/shCore.css">
- <link rel="stylesheet" type="text/css" href="syntaxhighlighter/styles/shThemeDefault.css">
+ <script type="text/javascript" src="static-files/syntaxhighlighter/scripts/shCore.js"></script>
+ <script type="text/javascript" src="static-files/syntaxhighlighter/scripts/shBrushCss.js"></script>
+ <script type="text/javascript" src="static-files/syntaxhighlighter/scripts/shBrushXml.js"></script>
+ <script type="text/javascript" src="static-files/syntaxhighlighter/scripts/shBrushJScript.js"></script>
+ <link rel="stylesheet" type="text/css" media="all" href="static-files/css/base.css">
+ <link rel="stylesheet" type="text/css" media="all" href="static-files/css/header.css">
+ <link rel="stylesheet" type="text/css" media="all" href="static-files/css/footer.css">
+ <link rel="stylesheet" type="text/css" media="all" href="static-files/css/sdk-docs.css">
+ <link rel="stylesheet" type="text/css" media="all" href="static-files/css/api-reference.css">
+ <link rel="stylesheet" type="text/css" href="static-files/syntaxhighlighter/styles/shCore.css">
+ <link rel="stylesheet" type="text/css" href="static-files/syntaxhighlighter/styles/shThemeDefault.css">
<!--[if IE]>
<style type="text/css">
.package-summary .module,
@@ -25,7 +25,7 @@
</style>
<![endif]-->
- <link rel="shortcut icon" type="image/x-icon" href="media/favicon.png">
+ <link rel="shortcut icon" type="image/x-icon" href="static-files/media/favicon.png">
<title></title>
</head>
<body>
@@ -178,7 +178,7 @@ <h3 class="sidebar-subsection-header"><a href="dev-guide/module-development/refe
<div role="contentinfo" id="footer">
<div class="section">
- <img alt="" src="media/footer-logo-med.png" class="footerlogo">
+ <img alt="" src="static-files/media/footer-logo-med.png" class="footerlogo">
<div id="social-footer">
<ul>
<li>get to know <b>add-ons</b></li>
@@ -204,8 +204,8 @@ <h3 class="sidebar-subsection-header"><a href="dev-guide/module-development/refe
</div>
</div>
-<script type="text/javascript" src="js/jquery.js"></script>
-<script type="text/javascript" src="js/main.js"></script>
+<script type="text/javascript" src="static-files/js/jquery.js"></script>
+<script type="text/javascript" src="static-files/js/main.js"></script>
</body>
View
0 static-files/css/api-reference.css → doc/static-files/css/api-reference.css
File renamed without changes.
View
0 static-files/css/base.css → doc/static-files/css/base.css
File renamed without changes.
View
0 static-files/css/footer.css → doc/static-files/css/footer.css
File renamed without changes.
View
0 static-files/css/header.css → doc/static-files/css/header.css
File renamed without changes.
View
0 static-files/css/sdk-docs.css → doc/static-files/css/sdk-docs.css
File renamed without changes.
View
0 static-files/js/jquery.js → doc/static-files/js/jquery.js
File renamed without changes.
View
24 static-files/js/main.js → doc/static-files/js/main.js
@@ -1,5 +1,4 @@
function run(jQuery) {
- var IDLE_PING_DELAY = 5000;
function highlightCode() {
$("code").parent("pre").addClass("brush: js");
@@ -95,29 +94,6 @@ function run(jQuery) {
}
}
- var serverNeedsKeepalive = true;
-
- function sendIdlePing() {
- jQuery.ajax({url:"/api/idle",
- cache: false,
- error: function(req) {
- if (req.status == 501 || req.status == 404) {
- // The server either isn't implementing idle, or
- // we're being served from static files; just bail
- // and stop pinging this API endpoint.
- serverNeedsKeepalive = false;
- }
- }});
- scheduleNextIdlePing();
- }
-
- function scheduleNextIdlePing() {
- if (serverNeedsKeepalive)
- window.setTimeout(sendIdlePing, IDLE_PING_DELAY);
- }
-
- if (window.location.protocol != "file:")
- scheduleNextIdlePing();
highlightCurrentPage();
highlightCode();
$(".syntaxhighlighter").width("auto");
View
175 doc/static-files/md/dev-guide/addon-development/content-scripts/access.md
@@ -0,0 +1,175 @@
+# Content Script Access #
+
+This page talks about the access content scripts have to:
+
+* DOM objects in the pages they are attached to
+* other content scripts
+* other scripts loaded by the page they are attached to
+
+## Access to the DOM ##
+
+Content scripts need to be able to access DOM objects in arbitrary web
+pages, but this could cause two potential security problems:
+
+1. JavaScript values from the content script could be accessed by the page,
+enabling a malicious page to steal data or call privileged methods.
+2. a malicious page could redefine standard functions and properties of DOM
+objects so they don't do what the add-on expects.
+
+To deal with this, content scripts access DOM objects via a proxy.
+Any changes they make are made to the proxy, and so are not visible to
+page content.
+
+The proxy is based on `XRayWrapper`, (also known as
+[`XPCNativeWrapper`](https://developer.mozilla.oreg/en/XPCNativeWrapper)).
+These wrappers give the user access to the native values of DOM functions
+and properties, even if they have been redefined by a script.
+
+For example: the page below redefines `window.confirm()` to return
+`true` without showing a confirmation dialog:
+
+<script type="syntaxhighlighter" class="brush: html"><![CDATA[
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html lang='en' xml:lang='en' xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <script>
+ window.confirm = function(message) {
+ return true;
+ }
+ &lt;/script>
+ </head>
+</html>
+
+</script>
+
+But thanks to the content proxy, a content script which calls
+`window.confirm()` will get the native implementation:
+
+ var widgets = require("widget");
+ var tabs = require("tabs");
+ var data = require("self").data;
+
+ var widget = widgets.Widget({
+ id: "transfer",
+ label: "Transfer",
+ content: "Transfer",
+ width: 100,
+ onClick: function() {
+ tabs.activeTab.attach({
+ // native implementation of window.confirm will be used
+ contentScript: "console.log(window.confirm('Transfer all my money?'));"
+ });
+ }
+ });
+
+ tabs.open(data.url("xray.html"));
+
+You can try out this example [using the builder](https://builder.addons.mozilla.org/addon/1013777/revision/4/).
+
+The proxy is transparent to content scripts: as far as the content script
+is concerned, it is accessing the DOM directly. But because it's not, some
+things that you might expect to work, won't. For example, if the page includes
+a library like [jQuery](http://www.jquery.com), or any other page script
+adds other objects to any DOM nodes, they won't be visible to the content
+script. So to use jQuery you'll typically have to add it as a content script,
+as in [this example](dev-guide/addon-development/content-scripts/reddit-example.html).
+
+### unsafeWindow ###
+
+If you really need direct access to the underlying DOM, you can use the
+global `unsafeWindow` object.
+
+To see the difference, try editing the
+[example in the builder](https://builder.addons.mozilla.org/addon/1013777/revision/4/)
+so the content script uses `unsafeWindow.confirm()` instead of
+`window.confirm()` (to edit the example, you'll need to create an account
+with the Add-on Builder and clone the original add-on). Alternatively, try out
+[the example here](https://builder.addons.mozilla.org/addon/1015979/revision/3/).
+
+Avoid using `unsafeWindow` if possible: it is the same concept as
+Greasemonkey's unsafeWindow, and the
+[warnings for that](http://wiki.greasespot.net/UnsafeWindow) apply equally
+here. Also, `unsafeWindow` isn't a supported API, so it could be removed or
+changed in a future version of the SDK.
+
+
+## Access to Other Content Scripts ##
+
+Content scripts loaded into the same document can interact
+with each other directly as well as with the web content itself. However,
+content scripts which have been loaded into different documents
+cannot interact with each other.
+
+For example:
+
+* if an add-on creates a single `panel` object and loads several content
+scripts into the panel, then they can interact with each other
+
+* if an add-on creates two `panel` objects and loads a script into each
+one, they can't interact with each other.
+
+* if an add-on creates a single `page-mod` object and loads several content
+scripts into the page mod, then only content scripts associated with the
+same page can interact with each other: if two different matching pages are
+loaded, content scripts attached to page A cannot interact with those attached
+to page B.
+
+The web content has no access to objects created by the content script, unless
+the content script explicitly makes them available.
+
+## Access to Page Scripts ##
+
+You can communicate between the content script and page scripts using
+[`postMessage()`](https://developer.mozilla.org/en/DOM/window.postMessage),
+but there's a twist: in early versions of the SDK, the global `postMessage()`
+function in content scripts was used for communicating between the content
+script and the main add-on code. Although this has been
+[deprecated in favor of `self.postMessage`](https://wiki.mozilla.org/Labs/Jetpack/Release_Notes/1.0b5#Major_Changes),
+the old globals are still supported, so you can't currently use
+`window.postMessage()`. You must use `document.defaultView.postMessage()`
+instead.
+
+The following page script uses
+[`window.addEventListener`](https://developer.mozilla.org/en/DOM/element.addEventListener)
+to listen for messages:
+
+<script type="syntaxhighlighter" class="brush: html"><![CDATA[
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html lang='en' xml:lang='en' xmlns="http://www.w3.org/1999/xhtml">
+
+ <head>
+ <script>
+ window.addEventListener("message", function(event) {
+ window.alert(event.data);
+ }, false);
+ &lt;/script>
+
+ </head>
+
+</html>
+
+</script>
+
+Content scripts can send it messages using `document.defaultView.postMessage()`:
+
+ var widgets = require("widget");
+ var tabs = require("tabs");
+ var data = require("self").data;
+
+ var widget = widgets.Widget({
+ id: "postMessage",
+ label: "demonstrate document.defaultView.postMessage",
+ contentURL: "http://www.mozilla.org/favicon.ico",
+ onClick: function() {
+ tabs.activeTab.attach({
+ contentScript: "document.defaultView.postMessage('hi there!', '*');"
+ });
+ }
+ });
+
+ tabs.open(data.url("listener.html"));
+
+You can see this add-on at
+[https://builder.addons.mozilla.org/addon/1013849/revision/8/](https://builder.addons.mozilla.org/addon/1013849/revision/8/).
View
60 doc/static-files/md/dev-guide/addon-development/content-scripts/loading.md
@@ -0,0 +1,60 @@
+
+# Loading Content Scripts #
+
+The constructors for content-script-using objects such as panel and page-mod
+define a group of options for loading content scripts:
+
+<pre>
+ contentScript string, array
+ contentScriptFile string, array
+ contentScriptWhen string
+</pre>
+
+We have already seen the `contentScript` option, which enables you to pass
+in the text of the script itself as a string literal. This version of the API
+avoids the need to maintain a separate file for the content script.
+
+The `contentScriptFile` option enables you to pass in the local file URL from
+which the content script will be loaded. To supply the file
+"my-content-script.js", located in the /data subdirectory under your package's
+root directory, use a line like:
+
+ // "data" is supplied by the "self" module
+ var data = require("self").data;
+ ...
+ contentScriptFile: data.url("my-content-script.js")
+
+Both `contentScript` and `contentScriptFile` accept an array of strings, so you
+can load multiple scripts, which can also interact directly with each other in
+the content process:
+
+ // "data" is supplied by the "self" module
+ var data = require("self").data;
+ ...
+ contentScriptFile:
+ [data.url("jquery-1.4.2.min.js"), data.url("my-content-script.js")]
+
+Scripts specified using contentScriptFile are loaded before those specified
+using contentScript. This enables you to load a JavaScript library like jQuery
+by URL, then pass in a simple script inline that can use jQuery.
+
+The `contentScriptWhen` option specifies when the content script(s) should be
+loaded. It takes one of three possible values:
+
+* "start" loads the scripts immediately after the document element for the
+page is inserted into the DOM. At this point the DOM content hasn't been
+loaded yet, so the script won't be able to interact with it.
+
+* "ready" loads the scripts after the DOM for the page has been loaded: that
+is, at the point the
+[DOMContentLoaded](https://developer.mozilla.org/en/Gecko-Specific_DOM_Events)
+event fires. At this point, content scripts are able to interact with the DOM
+content, but externally-referenced stylesheets and images may not have finished
+loading.
+
+* "end" loads the scripts after all content (DOM, JS, CSS, images) for the page
+has been loaded, at the time the
+[window.onload event](https://developer.mozilla.org/en/DOM/window.onload)
+fires.
+
+The default value is "end".
View
67 doc/static-files/md/dev-guide/addon-development/content-scripts/reddit-example.md
@@ -0,0 +1,67 @@
+# Reddit Example #
+
+This example add-on creates a panel containing the mobile version of Reddit.
+When the user clicks on the title of a story in the panel, the add-on opens
+the linked story in a new tab in the main browser window.
+
+To accomplish this the add-on needs to run a content script in the context of
+the Reddit page which intercepts mouse clicks on each title link and fetches the
+link's target URL. The content script then needs to send the URL to the add-on
+script.
+
+This is the complete add-on script:
+
+ var data = require("self").data;
+
+ var reddit_panel = require("panel").Panel({
+ width: 240,
+ height: 320,
+ contentURL: "http://www.reddit.com/.mobile?keep_extension=True",
+ contentScriptFile: [data.url("jquery-1.4.4.min.js"),
+ data.url("panel.js")]
+ });
+
+ reddit_panel.port.on("click", function(url) {
+ require("tabs").open(url);
+ });
+
+ require("widget").Widget({
+ id: "open-reddit-btn",
+ label: "Reddit",
+ contentURL: "http://www.reddit.com/static/favicon.ico",
+ panel: reddit_panel
+ });
+
+This code supplies two content scripts to the panel's constructor in the
+`contentScriptFile` option: the jQuery library and the script that intercepts
+link clicks.
+
+Finally, it registers a listener to the user-defined `click` event which in
+turn passes the URL into the `open` function of the
+[tabs](packages/addon-kit/docs/tabs.html) module.
+
+This is the `panel.js` content script that intercepts link clicks:
+
+ $(window).click(function (event) {
+ var t = event.target;
+
+ // Don't intercept the click if it isn't on a link.
+ if (t.nodeName != "A")
+ return;
+
+ // Don't intercept the click if it was on one of the links in the header
+ // or next/previous footer, since those links should load in the panel itself.
+ if ($(t).parents('#header').length || $(t).parents('.nextprev').length)
+ return;
+
+ // Intercept the click, passing it to the addon, which will load it in a tab.
+ event.stopPropagation();
+ event.preventDefault();
+ self.port.emit('click', t.toString());
+ });
+
+This script uses jQuery to interact with the DOM of the page and the
+`self.port.emit` function to pass URLs back to the add-on script.
+
+See the `examples/reddit-panel` directory for the complete example (including
+the content script containing jQuery).
View
0 ...development/content-scripts/using-port.md → ...development/content-scripts/using-port.md
File renamed without changes.
View
136 doc/static-files/md/dev-guide/addon-development/content-scripts/using-postmessage.md
@@ -0,0 +1,136 @@
+# Communicating using "postMessage()" #
+
+As an alternative to user-defined events content modules support the built-in
+`message` event. In most cases user-defined events are preferable to message
+events. However, the `context-menu` module does not support user-defined
+events, so to send messages from a content script to the add-on via a context
+menu object, you must use message events.
+
+## Handling Message Events in the Content Script ##
+
+To send a message from a content script, you use the `postMessage` function of
+the global `self` object:
+
+ self.postMessage(contentScriptMessage);
+
+This takes a single parameter, the message payload, which may be any
+<a href = "dev-guide/addon-development/content-scripts/using-port.html#json_serializable">JSON-serializable value</a>.
+
+To receive a message from the add-on script, use `self`'s `on` function:
+
+ self.on("message", function(addonMessage) {
+ // Handle the message
+ });
+
+Like all event-registration functions, this takes two parameters: the name
+of the event, and the handler function. The handler function is passed the
+message payload.
+
+## Handling Message Events in the Add-on Script ##
+
+To send a message to a content script, use the worker's `postMessage`
+function. Again, `panel` and `page` integrate `worker` directly:
+
+ // Post a message to the panel's content scripts
+ panel.postMessage(addonMessage);
+
+However, for `page-mod` objects you need to listen to the `onAttach` event
+and use the worker supplied to that:
+
+ var pageMod = require('page-mod').PageMod({
+ include: ['*'],
+ contentScript: pageModScript,
+ onAttach: function(worker) {
+ worker.postMessage(addonMessage);
+ }
+ });
+
+To receive messages from a content script, use the worker's `on` function.
+To simplify this most content modules provide an `onMessage` property as an
+argument to the constructor:
+
+ panel = require("panel").Panel({
+ onMessage: function(contentScriptMessage) {
+ // Handle message from the content script
+ }
+ });
+
+## Message Events Versus User-Defined Events ##
+
+You can use message events as an alternative to user-defined events:
+
+ var pageModScript = "window.addEventListener('mouseover', function(event) {" +
+ " self.postMessage(event.target.toString());" +
+ "}, false);";
+
+ var pageMod = require('page-mod').PageMod({
+ include: ['*'],
+ contentScript: pageModScript,
+ onAttach: function(worker) {
+ worker.on('message', function(message) {
+ console.log('mouseover: ' + message);
+ });
+ }
+ });
+
+The reason to prefer user-defined events is that as soon as you need to send
+more than one type of message, then both sending and receiving messages gets
+more complex.
+
+Suppose the content script wants to send `mouseout` events as well as
+`mouseover`. Now we have to embed the event type in the message payload, and
+implement a switch function in the receiver to dispatch the message:
+
+ var pageModScript = "window.addEventListener('mouseover', function(event) {" +
+ " self.postMessage({" +
+ " kind: 'mouseover'," +
+ " element: event.target.toString()" +
+ " });" +
+ "}, false);" +
+ "window.addEventListener('mouseout', function(event) {" +
+ " self.postMessage({" +
+ " kind: 'mouseout'," +
+ " element: event.target.toString()" +
+ " });" +
+ " }, false);"
+
+
+ var pageMod = require('page-mod').PageMod({
+ include: ['*'],
+ contentScript: pageModScript,
+ onAttach: function(worker) {
+ worker.on('message', function(message) {
+ switch(message.kind) {
+ case 'mouseover':
+ console.log('mouseover: ' + message.element);
+ break;
+ case 'mouseout':
+ console.log('mouseout: ' + message.element);
+ break;
+ }
+ });
+ }
+ });
+
+Implementing the same add-on with user-defined events is shorter and more
+readable:
+
+ var pageModScript = "window.addEventListener('mouseover', function(event) {" +
+ " self.port.emit('mouseover', event.target.toString());" +
+ "}, false);" +
+ "window.addEventListener('mouseout', function(event) {" +
+ " self.port.emit('mouseout', event.target.toString());" +
+ "}, false);";
+
+ var pageMod = require('page-mod').PageMod({
+ include: ['*'],
+ contentScript: pageModScript,
+ onAttach: function(worker) {
+ worker.port.on('mouseover', function(message) {
+ console.log('mouseover :' + message);
+ });
+ worker.port.on('mouseout', function(message) {
+ console.log('mouseout :' + message);
+ });
+ }
+ });
View
0 ...files/media/annotator/annotation-list.png → ...files/media/annotator/annotation-list.png
File renamed without changes
View
0 ...iles/media/annotator/annotation-panel.png → ...iles/media/annotator/annotation-panel.png
File renamed without changes
View
0 ...iles/media/annotator/annotator-design.png → ...iles/media/annotator/annotator-design.png
File renamed without changes
View
0 ...ic-files/media/annotator/editor-panel.png → ...ic-files/media/annotator/editor-panel.png
File renamed without changes
View
0 static-files/media/annotator/highlight.png → ...tatic-files/media/annotator/highlight.png
File renamed without changes
View
0 static-files/media/annotator/matcher.png → doc/static-files/media/annotator/matcher.png
File renamed without changes
View
0 static-files/media/annotator/pencil-off.png → ...atic-files/media/annotator/pencil-off.png
File renamed without changes
View
0 static-files/media/annotator/pencil-on.png → ...tatic-files/media/annotator/pencil-on.png
File renamed without changes
View
0 static-files/media/annotator/widget-icon.png → ...tic-files/media/annotator/widget-icon.png
File renamed without changes
View
0 static-files/media/bg-footer.png → doc/static-files/media/bg-footer.png
File renamed without changes
View
0 static-files/media/bg-header.png → doc/static-files/media/bg-header.png
File renamed without changes
View
0 static-files/media/commonjs-modules.jpg → doc/static-files/media/commonjs-modules.jpg
File renamed without changes
View
0 static-files/media/commonjs-translator.jpg → ...tatic-files/media/commonjs-translator.jpg
File renamed without changes
View
0 ...-files/media/content-scripting-events.png → ...-files/media/content-scripting-events.png
File renamed without changes
View
0 ...iles/media/content-scripting-overview.png → ...iles/media/content-scripting-overview.png
File renamed without changes
View
0 static-files/media/favicon.png → doc/static-files/media/favicon.png
File renamed without changes
View
0 static-files/media/firefox-32.png → doc/static-files/media/firefox-32.png
File renamed without changes
View
0 static-files/media/firefox-logo.png → doc/static-files/media/firefox-logo.png
File renamed without changes
View
0 static-files/media/footer-logo-med.png → doc/static-files/media/footer-logo-med.png
File renamed without changes
View
0 static-files/media/mozilla-tab.png → doc/static-files/media/mozilla-tab.png
File renamed without changes
View
0 static-files/media/multiple-workers.jpg → doc/static-files/media/multiple-workers.jpg
File renamed without changes
View
0 ...s/media/screenshots/default-panel-osx.png → ...s/media/screenshots/default-panel-osx.png
File renamed without changes
View
0 ...edia/screenshots/default-panel-ubuntu.png → ...edia/screenshots/default-panel-ubuntu.png
File renamed without changes
View
0 ...dia/screenshots/default-panel-windows.png → ...dia/screenshots/default-panel-windows.png
File renamed without changes
View
0 ...nshots/modules/context-menu-image-osx.png → ...nshots/modules/context-menu-image-osx.png
File renamed without changes
View
0 ...nshots/modules/notification-growl-osx.png → ...nshots/modules/notification-growl-osx.png
Diff not rendered.
View
0 ...ia/screenshots/modules/panel-tabs-osx.png → ...ia/screenshots/modules/panel-tabs-osx.png
Diff not rendered.
View
0 ...creenshots/modules/widget-content-osx.png → ...creenshots/modules/widget-content-osx.png
Diff not rendered.
View
0 ...a/screenshots/modules/widget-icon-osx.png → ...a/screenshots/modules/widget-icon-osx.png
Diff not rendered.
View
0 .../screenshots/modules/widget-panel-osx.png → .../screenshots/modules/widget-panel-osx.png
Diff not rendered.
View
0 ...reenshots/translator/context-menu-osx.png → ...reenshots/translator/context-menu-osx.png
Diff not rendered.
View
0 ...screenshots/translator/translated-osx.png → ...screenshots/translator/translated-osx.png
Diff not rendered.
View
0 .../media/screenshots/widget-panel-clock.png → .../media/screenshots/widget-panel-clock.png
Diff not rendered.
View
0 static-files/media/twitter-widget.png → doc/static-files/media/twitter-widget.png
Diff not rendered.
View
0 static-files/syntaxhighlighter/MIT-LICENSE → ...tatic-files/syntaxhighlighter/MIT-LICENSE
File renamed without changes.
View
0 ...s/syntaxhighlighter/scripts/shBrushCss.js → ...s/syntaxhighlighter/scripts/shBrushCss.js
File renamed without changes.
View
0 ...ntaxhighlighter/scripts/shBrushJScript.js → ...ntaxhighlighter/scripts/shBrushJScript.js
File renamed without changes.
View
0 ...s/syntaxhighlighter/scripts/shBrushXml.js → ...s/syntaxhighlighter/scripts/shBrushXml.js
File renamed without changes.
View
0 ...files/syntaxhighlighter/scripts/shCore.js → ...files/syntaxhighlighter/scripts/shCore.js
File renamed without changes.
View
0 ...files/syntaxhighlighter/styles/shCore.css → ...files/syntaxhighlighter/styles/shCore.css
File renamed without changes.
View
0 ...ntaxhighlighter/styles/shThemeDefault.css → ...ntaxhighlighter/styles/shThemeDefault.css
File renamed without changes.
View
2 packages/addon-kit/docs/page-mod.md
@@ -103,7 +103,7 @@ is loaded into its own execution context with its own copy of the content
scripts. In this case `onAttach` is called once for each loaded page, and the
add-on code will have a separate worker for each page:
-![Multiple workers](media/multiple-workers.jpg)
+![Multiple workers](static-files/media/multiple-workers.jpg)
This is demonstrated in the following example:
View
6 packages/addon-kit/docs/panel.md
@@ -39,19 +39,19 @@ This is what a panel with no custom styling looks like.
On OS X it will look like this:
-<img class="image-center" src="media/screenshots/default-panel-osx.png"
+<img class="image-center" src="static-files/media/screenshots/default-panel-osx.png"
alt="OS X panel default style">
<br>
On Windows 7 it will look like this:
-<img class="image-center" src="media/screenshots/default-panel-windows.png"
+<img class="image-center" src="static-files/media/screenshots/default-panel-windows.png"
alt="Windows 7 panel default style">
<br>
On Ubuntu it will look like this:
-<img class="image-center" src="media/screenshots/default-panel-ubuntu.png"
+<img class="image-center" src="static-files/media/screenshots/default-panel-ubuntu.png"
alt="Ubuntu panel default style">
<br>
View
2 packages/addon-kit/docs/widget.md
@@ -80,7 +80,7 @@ Nuvola icon set, http://www.icon-king.com/projects/nuvola/ which is made
available under the LGPL 2.1:
http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html -->
-<img class="image-center" src="media/screenshots/widget-panel-clock.png"
+<img class="image-center" src="static-files/media/screenshots/widget-panel-clock.png"
alt="Panel attached to a widget">
<br>
View
24 python-lib/cuddlefish/__init__.py
@@ -2,6 +2,7 @@
import os
import optparse
import glob
+import webbrowser
from copy import copy
import simplejson as json
@@ -495,25 +496,18 @@ def run(arguments=sys.argv[1:], target_cfg=None, pkg_cfg=None,
test_cfx(env_root, options.verbose)
return
elif command == "docs":
- import subprocess
- import time
- import cuddlefish.server
-
- print >>stdout, "One moment."
- popen = subprocess.Popen([sys.executable,
- cuddlefish.server.__file__,
- 'daemonic'])
- # TODO: See if there's actually a way to block on
- # a particular event occurring, rather than this
- # relatively arbitrary/generous amount.
- time.sleep(cuddlefish.server.IDLE_WEBPAGE_TIMEOUT * 2)
+ from cuddlefish.docs import generate
+ if len(args) > 1:
+ docs_home = generate.generate_docs(env_root, filename=args[1])
+ else:
+ docs_home = generate.generate_docs(env_root)
+ webbrowser.open(docs_home)
return
elif command == "sdocs":
- import cuddlefish.server
+ from cuddlefish.docs import generate
# TODO: Allow user to change this filename via cmd line.
- filename = 'addon-sdk-docs.tgz'
- cuddlefish.server.generate_static_docs(env_root, filename, options.baseurl)
+ filename = generate.generate_static_docs(env_root, base_url=options.baseurl)
print >>stdout, "Wrote %s." % filename
return
View
0 python-lib/cuddlefish/docs/__init__.py
No changes.
View
0 python-lib/cuddlefish/apiparser.py → python-lib/cuddlefish/docs/apiparser.py
File renamed without changes.
View
0 python-lib/cuddlefish/apirenderer.py → python-lib/cuddlefish/docs/apirenderer.py
File renamed without changes.
View
224 python-lib/cuddlefish/docs/generate.py
@@ -0,0 +1,224 @@
+import os
+import sys
+import shutil
+import hashlib
+import tarfile
+import StringIO
+
+from cuddlefish import packaging
+from cuddlefish import Bunch
+from cuddlefish.docs import apiparser
+from cuddlefish.docs import apirenderer
+from cuddlefish.docs import webdocs
+import simplejson as json
+
+DOCS_DIR = "doc"
+DIGEST = "status.md5"
+TGZ_FILENAME = "addon-sdk-docs.tgz"
+
+def clean_generated_docs(docs_dir):
+ index_file = os.path.join(docs_dir, "index.html")
+ if os.path.exists(index_file):
+ os.remove(index_file)
+ dev_guide_dir = os.path.join(docs_dir, "dev-guide")
+ if os.path.exists(dev_guide_dir):
+ shutil.rmtree(dev_guide_dir)
+ api_doc_dir = os.path.join(docs_dir, "packages")
+ if os.path.exists(api_doc_dir):
+ shutil.rmtree(api_doc_dir)
+
+def generate_static_docs(env_root, base_url=None):
+ docs_dir = os.path.join(env_root, DOCS_DIR)
+ clean_generated_docs(docs_dir)
+ generate_docs(env_root, base_url=base_url, stdout=StringIO.StringIO())
+ tgz = tarfile.open(TGZ_FILENAME, 'w:gz')
+ tgz.add(docs_dir, DOCS_DIR)
+ tgz.close()
+ return TGZ_FILENAME
+
+def generate_docs(env_root, base_url=None, filename=None, stdout=sys.stdout):
+ docs_dir = os.path.join(env_root, DOCS_DIR)
+ base_url = calculate_base_url(base_url, docs_dir)
+ # if we were given a filename, just generate the named file
+ # and return its URL
+ if filename:
+ return generate_named_file(env_root, base_url, filename)
+ # if the static docs dir doesn't exist, generate everything
+ if not os.path.exists(os.path.join(docs_dir, "index.html")):
+ print >>stdout, "Generating documentation..."
+ generate_docs_from_scratch(env_root, base_url, docs_dir)
+ current_status = calculate_current_status(env_root)
+ open(os.path.join(env_root, DOCS_DIR, DIGEST), "w").write(current_status)
+ else:
+ current_status = calculate_current_status(env_root)
+ previous_status_file = os.path.join(env_root, DOCS_DIR, DIGEST)
+ docs_are_up_to_date = False
+ if os.path.exists(previous_status_file):
+ docs_are_up_to_date = current_status == open(previous_status_file, "r").read()
+ # if the docs are not up to date, generate everything
+ if not docs_are_up_to_date:
+ print >>stdout, "Regenerating documentation..."
+ clean_generated_docs(docs_dir)
+ generate_docs_from_scratch(env_root, base_url, docs_dir)
+ open(os.path.join(env_root, DOCS_DIR, DIGEST), "w").write(current_status)
+ return base_url + "index.html"
+
+def calculate_base_url(base_url, docs_dir):
+ if base_url == None:
+ base_url_path = docs_dir
+ # this is to ensure the path starts with "/"
+ # whether or not it's on Windows
+ # there might be a better way
+ if not docs_dir.startswith("/"):
+ base_url_path = "/" + base_url_path
+ base_url_path_pieces = base_url_path.split(os.sep)
+ base_url = "file://" + "/".join(base_url_path_pieces) + "/"
+ return base_url
+
+def generate_named_file(env_root, base_url, filename):
+ docs_dir = os.path.join(env_root, DOCS_DIR)
+ web_docs = webdocs.WebDocs(env_root, base_url)
+
+ # next, generate api doc or guide doc
+ abs_path = os.path.abspath(filename)
+ if abs_path.startswith(os.path.join(env_root, 'packages')):
+ return generate_api_doc(env_root, abs_path, web_docs)
+ elif abs_path.startswith(os.path.join(env_root, DOCS_DIR, 'dev-guide-source')):
+ return generate_guide_doc(env_root, abs_path, web_docs)
+ else:
+ raise ValueError("Not a valid path to a documentation file")
+
+# this function builds a hash of the name and last modification date of:
+# * every file in "packages" which ends in ".md"
+# * every file in "static-files" which does not start with "."
+def calculate_current_status(env_root):
+ current_status = hashlib.md5()
+ package_src_dir = os.path.join(env_root, "packages")
+ for (dirpath, dirnames, filenames) in os.walk(package_src_dir):
+ for filename in filenames:
+ if filename.endswith(".md"):
+ current_status.update(filename)
+ current_status.update(str(os.path.getmtime(os.path.join(dirpath, filename))))
+ guide_src_dir = os.path.join(env_root, DOCS_DIR, "dev-guide-source")
+ for (dirpath, dirnames, filenames) in os.walk(guide_src_dir):
+ for filename in filenames:
+ if filename.endswith(".md"):
+ current_status.update(filename)
+ current_status.update(str(os.path.getmtime(os.path.join(dirpath, filename))))
+ return current_status.digest()
+
+def generate_docs_from_scratch(env_root, base_url, docs_dir):
+ web_docs = webdocs.WebDocs(env_root, base_url)
+ clean_generated_docs(docs_dir)
+
+ # py2.5 doesn't have ignore=, so we delete tempfiles afterwards. If we
+ # required >=py2.6, we could use ignore=shutil.ignore_patterns("*~")
+ for (dirpath, dirnames, filenames) in os.walk(docs_dir):
+ for n in filenames:
+ if n.endswith("~"):
+ os.unlink(os.path.join(dirpath, n))
+
+ # generate api docs from all packages
+ os.mkdir(os.path.join(docs_dir, "packages"))
+ # create the index file and save that
+ pkg_cfg = packaging.build_pkg_cfg(env_root)
+ index = json.dumps(packaging.build_pkg_index(pkg_cfg))
+ index_path = os.path.join(docs_dir, "packages", 'index.json')
+ open(index_path, 'w').write(index)
+
+ # for each package, generate its docs
+ for pkg_name, pkg in pkg_cfg['packages'].items():
+ src_dir = pkg.root_dir
+ dest_dir = os.path.join(docs_dir, "packages", pkg_name)
+ os.mkdir(dest_dir)
+
+ src_readme = os.path.join(src_dir, "README.md")
+ if os.path.exists(src_readme):
+ shutil.copyfile(src_readme,
+ os.path.join(dest_dir, "README.md"))
+
+ # create the package page
+ package_filename = os.path.join(dest_dir, pkg_name + ".html")
+ if not os.path.exists(package_filename):
+ package_doc_html = web_docs.create_package_page(src_dir)
+ open(package_filename, "w").write(package_doc_html)
+
+ # generate all the API docs
+ docs_src_dir = os.path.join(src_dir, "doc")
+ if os.path.isdir(os.path.join(src_dir, "docs")):
+ docs_src_dir = os.path.join(src_dir, "docs")
+ generate_file_tree(env_root, docs_src_dir, web_docs, generate_api_doc)
+
+ # generate all the guide docs
+ dev_guide_src = os.path.join(env_root, DOCS_DIR, "dev-guide-source")
+ generate_file_tree(env_root, dev_guide_src, web_docs, generate_guide_doc)
+
+ # make /md/dev-guide/welcome.html the top level index file
+ shutil.copy(os.path.join(env_root, DOCS_DIR, 'dev-guide', 'welcome.html'), \
+ os.path.join(docs_dir, 'index.html'))
+
+def generate_file_tree(env_root, src_dir, web_docs, generate_file):
+ for (dirpath, dirnames, filenames) in os.walk(src_dir):
+ assert dirpath.startswith(src_dir) # what is this for??
+ for filename in filenames:
+ if filename.endswith("~"):
+ continue
+ src_path = os.path.join(dirpath, filename)
+ generate_file(env_root, src_path, web_docs)
+
+def generate_api_doc(env_root, src_dir, web_docs):
+ if src_dir.endswith(".md"):
+ dest_dir, filename = get_api_doc_dest_path(env_root, src_dir)
+ if not os.path.exists(dest_dir):
+ os.makedirs(dest_dir)
+
+ # parse and JSONify the API docs
+ docs_md = open(src_dir, 'r').read()
+ docs_parsed = list(apiparser.parse_hunks(docs_md))
+ docs_json = json.dumps(docs_parsed)
+ dest_path_json = os.path.join(dest_dir, filename) + ".json"
+ replace_file(dest_path_json, docs_json)
+
+ # write the HTML div files
+ docs_div = apirenderer.json_to_div(docs_parsed, src_dir)
+ dest_path_div = os.path.join(dest_dir, filename) + ".div"
+ replace_file(dest_path_div, docs_div)
+
+ # write the standalone HTML files
+ docs_html = web_docs.create_module_page(src_dir)
+ dest_path_html = os.path.join(dest_dir, filename) + ".html"
+ replace_file(dest_path_html, docs_html)
+
+ return dest_path_html
+
+def generate_guide_doc(env_root, src_dir, web_docs):
+ if src_dir.endswith(".md"):
+ dest_dir, filename = get_guide_doc_dest_path(env_root, src_dir)
+ if not os.path.exists(dest_dir):
+ os.makedirs(dest_dir)
+ # write the standalone HTML files
+ docs_html = web_docs.create_guide_page(src_dir)
+ dest_path_html = os.path.join(dest_dir, filename) + ".html"
+ replace_file(dest_path_html, docs_html)
+ return dest_path_html
+
+def replace_file(dest_path, file_contents):
+ if os.path.exists(dest_path):
+ os.remove(dest_path)
+ open(dest_path, "w").write(file_contents)
+
+# Given the full path to an API source file, and the root,
+# return a tuple of:
+# 1) the full path to the corresponding HTML file, without the filename
+# 2) the filename without the extension
+def get_guide_doc_dest_path(env_root, src_dir):
+ src_dir_relative = src_dir[len(os.path.join(env_root, DOCS_DIR, "dev-guide-source")) + 1:]
+ return os.path.split(os.path.join(env_root, DOCS_DIR, "dev-guide", src_dir_relative)[:-3])
+
+# Given the full path to a dev guide source file, and the root,
+# return a tuple of:
+# 1) the full path to the corresponding HTML file, without the filename
+# 2) the filename without the extension
+def get_api_doc_dest_path(env_root, src_dir):
+ src_dir_relative = src_dir[len(env_root) + 1:]
+ return os.path.split(os.path.join(env_root, DOCS_DIR, src_dir_relative)[:-3])
View
6 python-lib/cuddlefish/webdocs.py → python-lib/cuddlefish/docs/webdocs.py
@@ -4,10 +4,10 @@
from cuddlefish import packaging
from cuddlefish import Bunch
-from cuddlefish import apiparser
-from cuddlefish import apirenderer
+from cuddlefish.docs import apiparser
+from cuddlefish.docs import apirenderer
-INDEX_PAGE = '/static-files/base.html'
+INDEX_PAGE = '/doc/static-files/base.html'
BASE_URL_INSERTION_POINT = '<base '
HIGH_LEVEL_PACKAGE_SUMMARIES = '<li id="high-level-package-summaries">'
LOW_LEVEL_PACKAGE_SUMMARIES = '<li id="low-level-package-summaries">'
View
119 python-lib/cuddlefish/server.py
@@ -17,9 +17,10 @@
from cuddlefish import packaging
from cuddlefish import Bunch
-from cuddlefish import apiparser
-from cuddlefish import apirenderer
-from cuddlefish import webdocs
+from cuddlefish.docs import apiparser
+from cuddlefish.docs import apirenderer
+from cuddlefish.docs import webdocs
+from cuddlefish.docs import generate
import simplejson as json
try:
@@ -311,118 +312,6 @@ def start(env_root=None, host=DEFAULT_HOST, port=DEFAULT_PORT,
except KeyboardInterrupt:
print "Ctrl-C received, exiting."
-def generate_static_docs(env_root, tgz_filename, base_url = ''):
- web_docs = webdocs.WebDocs(env_root, base_url)
- server = Server(env_root, web_docs,
- task_queue=None,
- expose_privileged_api=False)
- staging_dir = os.path.join(env_root, "addon-sdk-docs")
- if os.path.exists(staging_dir):
- shutil.rmtree(staging_dir)
-
- # first, copy static-files
- shutil.copytree(server.root, staging_dir)
- # py2.5 doesn't have ignore=, so we delete tempfiles afterwards. If we
- # required >=py2.6, we could use ignore=shutil.ignore_patterns("*~")
- for (dirpath, dirnames, filenames) in os.walk(staging_dir):
- for n in filenames:
- if n.endswith("~"):
- os.unlink(os.path.join(dirpath, n))
-
- # then copy docs from each package
- os.mkdir(os.path.join(staging_dir, "packages"))
-
- pkg_cfg = packaging.build_pkg_cfg(server.env_root)
-
- # starting with the (generated) index file
- index = json.dumps(packaging.build_pkg_index(pkg_cfg))
- index_path = os.path.join(staging_dir, "packages", 'index.json')
- open(index_path, 'w').write(index)
-
- # and every doc-like thing in the package
- for pkg_name, pkg in pkg_cfg['packages'].items():
- src_dir = pkg.root_dir
- dest_dir = os.path.join(staging_dir, "packages", pkg_name)
- if not os.path.exists(dest_dir):
- os.mkdir(dest_dir)
-
- # TODO: This is a DRY violation from main.js. We should
- # really move the common logic/names to cuddlefish.packaging.
- src_readme = os.path.join(src_dir, "README.md")
- if os.path.exists(src_readme):
- shutil.copyfile(src_readme,
- os.path.join(dest_dir, "README.md"))
-
- # create the package page
- package_doc_html = web_docs.create_package_page(src_dir)
- open(os.path.join(dest_dir, pkg_name + ".html"), "w")\
- .write(package_doc_html)
-
- docs_src_dir = os.path.join(src_dir, "doc")
- docs_dest_dir = os.path.join(dest_dir, "doc")
- if os.path.isdir(os.path.join(src_dir, "docs")):
- docs_src_dir = os.path.join(src_dir, "docs")
- docs_dest_dir = os.path.join(dest_dir, "docs")
- if not os.path.exists(docs_dest_dir):
- os.mkdir(docs_dest_dir)
- for (dirpath, dirnames, filenames) in os.walk(docs_src_dir):
- assert dirpath.startswith(docs_src_dir)
- relpath = dirpath[len(docs_src_dir)+1:]
- for dirname in dirnames:
- dest_path = os.path.join(docs_dest_dir, relpath, dirname)
- if not os.path.exists(dest_path):
- os.mkdir(dest_path)
- for filename in filenames:
- if filename.endswith("~"):
- continue
- src_path = os.path.join(dirpath, filename)
- dest_path = os.path.join(docs_dest_dir, relpath, filename)
- shutil.copyfile(src_path, dest_path)
- if filename.endswith(".md"):
- # parse and JSONify the API docs
- docs_md = open(src_path, 'r').read()
- docs_parsed = list(apiparser.parse_hunks(docs_md))
- docs_json = json.dumps(docs_parsed)
- open(dest_path + ".json", "w").write(docs_json)
- # write the HTML div files
- docs_div = apirenderer.json_to_div(docs_parsed, src_path)
- open(dest_path + ".div", "w").write(docs_div)
- # write the standalone HTML files
- docs_html = web_docs.create_module_page(src_path)
- open(dest_path[:-3] + ".html", "w").write(docs_html)
-
- dev_guide_src = os.path.join(server.root, 'md', 'dev-guide')
- dev_guide_dest = os.path.join(staging_dir, 'dev-guide')
- if not os.path.exists(dev_guide_dest):
- os.mkdir(dev_guide_dest)
- for (dirpath, dirnames, filenames) in os.walk(dev_guide_src):
- assert dirpath.startswith(dev_guide_src)
- relpath = dirpath[len(dev_guide_src)+1:]
- for dirname in dirnames:
- dest_path = os.path.join(dev_guide_dest, relpath, dirname)
- if not os.path.exists(dest_path):
- os.mkdir(dest_path)
- for filename in filenames:
- if filename.endswith("~"):
- continue
- src_path = os.path.join(dirpath, filename)
- dest_path = os.path.join(dev_guide_dest, relpath, filename)
- if filename.endswith(".md"):
- # write the standalone HTML files
- docs_html = web_docs.create_guide_page(src_path)
- open(dest_path[:-3] + ".html", "w").write(docs_html)
-
- # make /md/dev-guide/welcome.html the top level index file
- shutil.copy(os.path.join(dev_guide_dest, 'welcome.html'), \
- os.path.join(staging_dir, 'index.html'))
-
-
- # finally, build a tarfile out of everything
- tgz = tarfile.open(tgz_filename, 'w:gz')
- tgz.add('addon-sdk-docs', 'addon-sdk-docs')
- tgz.close()
- shutil.rmtree(staging_dir)
-
def run_app(harness_root_dir, harness_options,
app_type, binary=None, profiledir=None, verbose=False,
timeout=None, logfile=None, addons=None, args=None, norun=None,
View
2 python-lib/cuddlefish/tests/__init__.py
@@ -31,7 +31,7 @@ def get_tests():
if len(test.examples) > 0:
tests.append(doctest.DocTestCase(test))
- md_dir = os.path.join(env_root, 'static-files', 'md')
+ md_dir = os.path.join(env_root, 'dev-guide')
doctest_opts = (doctest.NORMALIZE_WHITESPACE |
doctest.REPORT_UDIFF)
for dirpath, dirnames, filenames in os.walk(md_dir):
View
0 ...-files/static-files/md/dev-guide/no_h1.md → ...tatic-files/doc/dev-guide-source/no_h1.md
File renamed without changes.
View
0 ...iles/static-files/md/dev-guide/welcome.md → ...tic-files/doc/dev-guide-source/welcome.md
File renamed without changes.
View
0 ...tests/static-files/static-files/base.html → ...s/static-files/doc/static-files/base.html
File renamed without changes.
View
0 ...ests/static-files/static-files/index.html → .../static-files/doc/static-files/index.html
File renamed without changes.
View
1 python-lib/cuddlefish/tests/static-files/doc/status.md5
@@ -0,0 +1 @@
+ Xh3HΏ���� 2|
View
2 python-lib/cuddlefish/tests/test_apiparser.py
@@ -1,7 +1,7 @@
import os
import unittest
-from cuddlefish.apiparser import parse_hunks, ParseError
+from cuddlefish.docs.apiparser import parse_hunks, ParseError
tests_path = os.path.abspath(os.path.dirname(__file__))
static_files_path = os.path.join(tests_path, "static-files")
View
4 python-lib/cuddlefish/tests/test_apirenderer.py
@@ -1,8 +1,8 @@
import os
import unittest
-from cuddlefish.apiparser import parse_hunks, ParseError
-from cuddlefish.apirenderer import md_to_html
+from cuddlefish.docs.apiparser import parse_hunks, ParseError
+from cuddlefish.docs.apirenderer import md_to_html