Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjim <jim@38b22f21-9aea-0310-abfc-843a9883df58>2008-04-14 04:28:00 (GMT)
committer jim <jim@38b22f21-9aea-0310-abfc-843a9883df58>2008-04-14 04:28:00 (GMT)
commitb25e1b8e5136b5b1ec8da641a92cc112e4e31e8f (patch)
treed3e37b4b060ba427f6cec704b48510e06422c919
parent254ad19e4a760ceda27dc93378b5cc89e192bf88 (diff)
change Help to use an offline snapshot of manual, and snapshot tool
git-svn-id: https://exe.svn.sourceforge.net/svnroot/exe/trunk@3469 38b22f21-9aea-0310-abfc-843a9883df58
-rw-r--r--NEWS2
-rw-r--r--exe/webui/docs/manual/eXe_manual.css54
-rw-r--r--exe/xului/templates/mainpage.xul2
-rwxr-xr-xtools/getManual.py189
4 files changed, 246 insertions, 1 deletions
diff --git a/NEWS b/NEWS
index 092fe68..84ca5f0 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,6 @@
+* Add offline snapshot of manual, release notes
* Add ability to translate tooltips
+* Add ability for multiple users on posix systems to each run eXe
* Fix handling of multi-select questions with 10 or more options
* Fix tip display at right edge of windows
* Improve Wiki Article idevice handling of pages without content div
diff --git a/exe/webui/docs/manual/eXe_manual.css b/exe/webui/docs/manual/eXe_manual.css
new file mode 100644
index 0000000..147d7d2
--- /dev/null
+++ b/exe/webui/docs/manual/eXe_manual.css
@@ -0,0 +1,54 @@
+/* thumbnails */
+div.thumb {
+ margin-bottom: .5em;
+ border-style: solid;
+ border-color: white;
+ width: auto;
+}
+div.thumbinner {
+ border: 1px solid #ccc;
+ padding: 3px !important;
+ background-color: #f9f9f9;
+ font-size: 94%;
+ text-align: center;
+ overflow: hidden;
+}
+html .thumbimage {
+ border: 1px solid #ccc;
+}
+html .thumbcaption {
+ border: none;
+ text-align: left;
+ line-height: 1.4em;
+ padding: 3px !important;
+ font-size: 94%;
+}
+div.magnify {
+ float: right;
+ border: none !important;
+ background: none !important;
+}
+div.magnify a, div.magnify img {
+ /* display: block; */
+ display: none;
+ border: none !important;
+ background: none !important;
+}
+div.tright {
+ clear: right;
+ float: right;
+ border-width: .5em 0 .8em 1.4em;
+}
+div.tleft {
+ float: left;
+ clear: left;
+ margin-right: .5em;
+ border-width: .5em 1.4em .8em 0;
+}
+img.thumbborder {
+ border: 1px solid #dddddd;
+}
+.hiddenStructure {
+ display: none;
+}
+
diff --git a/exe/xului/templates/mainpage.xul b/exe/xului/templates/mainpage.xul
index cee2eab..719617c 100644
--- a/exe/xului/templates/mainpage.xul
+++ b/exe/xului/templates/mainpage.xul
@@ -97,7 +97,7 @@
</menu>
<menu n:render="translate" id="help-menu" label="Help" accesskey="h">
<menupopup id="help-popup">
- <menuitem n:render="translate" label="Online eXe Manual" accesskey="m" oncommand="browseURL('http://exelearning.org/manual.php')"/>
+ <menuitem n:render="translate" label="eXe Manual" accesskey="m" oncommand="browseURL('file://%s/docs/manual/Online_manual.html')"/>
<menuitem n:render="translate" label="Release Notes" accesskey="n" oncommand="browseURL('file://%s/NEWS')"/>
<menuseparator/>
<!-- <menuitem n:render="translate" label="Register Online" accesskey="R" oncommand="registerOnline()"/> -->
diff --git a/tools/getManual.py b/tools/getManual.py
new file mode 100755
index 0000000..f3d6210
--- /dev/null
+++ b/tools/getManual.py
@@ -0,0 +1,189 @@
+#!/usr/bin/python -u
+#
+# Make a snapshot of the eXe Online Manual for offline use
+#
+# Copyright (c) 2008 James W. Tittsler <jwt@OnJapan.net>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+#
+# 20080118 jwt@OnJapan.net -- package WikiEducator collection as
+# Common Cartridge or Content Package
+# 20080414 jim@exelearning.org -- snapshot eXe manual from WikiEducator
+"""make a snapshot of the eXe manual from WikiEducator"""
+
+# All of the articles in this collection will be downloaded
+url = 'http://wikieducator.org/WikiEducator:Collections/EXe_Manual'
+manual_dir = 'exe/webui/docs/manual'
+
+import os
+import sys
+import re
+from fnmatch import fnmatch
+from urllib import unquote
+import urllib2
+import cgi
+# Try to work even with no python path
+try:
+ from exe.engine.beautifulsoup import BeautifulSoup, Tag
+except ImportError, error:
+ if str(error) == "No module named exe.engine.beautifulsoup":
+ exePath = os.path.abspath(sys.argv[0])
+ exeDir = os.path.dirname(exePath)
+ pythonPath = os.path.split(exeDir)[0]
+ sys.path.insert(0, pythonPath)
+ from exe.engine.beautifulsoup import BeautifulSoup, Tag
+ else:
+ raise error
+
+# remove old HTML and image files
+for file in os.listdir(manual_dir):
+ if fnmatch(file, '*.html') or fnmatch(file, '*.jpg') \
+ or fnmatch(file, '*.jpeg') or fnmatch(file, '*.gif') \
+ or fnmatch(file, '*.png'):
+ os.remove(os.path.join(manual_dir, file))
+
+def url_join(a, b):
+ url = a
+ if not a.endswith('/'):
+ url += '/'
+ if b.startswith('/'):
+ url += b[1:]
+ else:
+ url += b
+ return url
+
+def page_name(a, suffix=''):
+ """make filesystem name based on unquoted base part of URL"""
+ pn = unquote(a.split('/')[-1])
+ if suffix <> '' and not pn.endswith(suffix):
+ pn += suffix
+ return cgi.escape(pn, True)
+
+def fix_link(url):
+ if url.startswith('http://'):
+ return url
+ elif url.startswith('User:'):
+ return 'http://wikieducator.org/' + url
+ return url.split('/')[-1] + '.html'
+
+if not url.startswith('http://wikieducator.org/') \
+ and not url.startswith('http://www.wikieducator.org/'):
+ print "URL must start with http://wikieducator.org/"
+ sys.exit(-1)
+
+html_prologue = '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+<title>eXe</title>
+<style type="text/css">
+@import url(eXe_manual.css);
+</style>
+</head>
+<body>
+'''
+html_epilogue = '''</body></html>
+'''
+
+base_url = 'http://wikieducator.org/'
+collection = urllib2.urlopen(url)
+soup = BeautifulSoup(collection)
+
+# make sure the URL is a collection, and not a "page not found" page
+if not soup.find('span', {'class': 'mw-headline'}):
+ print 'missing or malformed collection page'
+ sys.exit()
+
+collection_title = str(soup.find('span', {'class': 'mw-headline'}).string).strip()
+
+print "fetching manual..."
+sys.stdout.flush()
+
+for page in soup('dd'):
+ if not page.a:
+ continue
+ print ' ', page.a.string,
+ sys.stdout.flush()
+ page_url = url_join(base_url, page.a['href'])
+ #print page_url,"</li>"
+ sys.stdout.flush()
+ p1 = urllib2.urlopen(page_url)
+ p1_soup = BeautifulSoup(p1)
+ #print p1_soup.find(id = 'bodyContent')
+ body = p1_soup.find(id = 'content')
+ # remove some bits
+ body.find(id = 'siteNotice').extract()
+ body.find(id = 'siteSub').extract()
+ body.find(id = 'contentSub').extract()
+ body.find(id = 'jump-to-nav').extract()
+ #if body.find(id = 'toc'):
+ # body.find(id = 'toc').extract()
+ if body.find(id = 'printfooter'):
+ body.find(id = 'printfooter').extract()
+ #if body.find('div', {'class': 'navigation'}):
+ # body.find('div', {'class': 'navigation'}).extract()
+ if body.find('div', {'class': 'printfooter'}):
+ body.find('div', {'class': 'printfooter'}).extract()
+ if body.find('table', {'class': 'workinprogress'}):
+ body.find('table', {'class': 'workinprogress'}).extract()
+ if body.find(id = 'catlinks'):
+ body.find(id = 'catlinks').extract()
+ # disable local links
+ for link in body.findAll('a'):
+ if not link.has_key('class'):
+ if link.has_key('name'):
+ continue
+ link['href'] = fix_link(link['href'])
+ elif link['class'].find('external') > -1:
+ link['target'] = '_blank'
+ elif link['class'].find('image') > -1:
+ #print " image link:", link
+ tag = Tag(soup, 'span', [('class', 'removed_img_link')])
+ tag.insert(0, link.contents[0])
+ link.replaceWith(tag)
+ else:
+ #print " non-ext link:",link
+ tag = Tag(soup, 'span', [('class', 'removed_link')])
+ tag.insert(0, link.contents[0])
+ link.replaceWith(tag)
+
+ # fetch all the images
+ for img in body.findAll('img'):
+ img_url = str(img['src'])
+ if not img_url.startswith('http://'):
+ img_url = url_join(base_url, img_url)
+ #print " ", img_url
+ img_contents = urllib2.urlopen(img_url)
+ open(os.path.join(manual_dir, page_name(img_url)), 'wb').write(img_contents.read())
+ img['src'] = page_name(img_url)
+ #print " ", img
+ print '.',
+ sys.stdout.flush()
+
+ f = open(os.path.join(manual_dir, page_name(page_url, '.html')), 'wt')
+ f.write(html_prologue)
+ f.write(str(body))
+ f.write(html_epilogue)
+ f.close()
+
+ print