diff options
author | Rogan Creswick <creswick@galois.com> | 2012-03-30 17:07:02 -0700 |
---|---|---|
committer | Rogan Creswick <creswick@galois.com> | 2012-03-30 17:07:02 -0700 |
commit | f6ab6622aab00fe7c2f4c3dc41f786ebbe0f0d73 (patch) | |
tree | 870111038542cd27153e1396ebdc063573249689 /tools/addon-sdk-1.4/python-lib/cuddlefish/docs/webdocs.py |
initial revision
Diffstat (limited to 'tools/addon-sdk-1.4/python-lib/cuddlefish/docs/webdocs.py')
-rw-r--r-- | tools/addon-sdk-1.4/python-lib/cuddlefish/docs/webdocs.py | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/tools/addon-sdk-1.4/python-lib/cuddlefish/docs/webdocs.py b/tools/addon-sdk-1.4/python-lib/cuddlefish/docs/webdocs.py new file mode 100644 index 0000000..5822745 --- /dev/null +++ b/tools/addon-sdk-1.4/python-lib/cuddlefish/docs/webdocs.py @@ -0,0 +1,200 @@ +import sys, os, re, errno +import markdown +import simplejson as json +import cgi + +from cuddlefish import packaging +from cuddlefish import Bunch +from cuddlefish.docs import apiparser +from cuddlefish.docs import apirenderer +from cuddlefish._version import get_versions + +INDEX_PAGE = '/doc/static-files/base.html' +BASE_URL_INSERTION_POINT = '<base ' +VERSION_INSERTION_POINT = '<div id="version">' +HIGH_LEVEL_PACKAGE_SUMMARIES = '<li id="high-level-package-summaries">' +LOW_LEVEL_PACKAGE_SUMMARIES = '<li id="low-level-package-summaries">' +CONTENT_ID = '<div id="main-content">' +TITLE_ID = '<title>' +DEFAULT_TITLE = 'Add-on SDK Documentation' + +def get_modules(modules_json): + modules = [] + for name in modules_json: + typ = modules_json[name][0] + if typ == "directory": + sub_modules = get_modules(modules_json[name][1]) + for sub_module in sub_modules: + modules.append([name, sub_module[0]]) + elif typ == "file": + if not name.startswith(".") and name.endswith('.js'): + modules.append([name[:-3]]) + return modules + +def get_documented_modules(package_name, modules_json, doc_path): + modules = get_modules(modules_json) + documented_modules = [] + for module in modules: + path = os.path.join(*module) + if module_md_exists(doc_path, path): + documented_modules.append(module) + if package_name == "addon-kit": + # hack for bug 664001, self-maker.js is in api-utils, self.md is in + # addon-kit. Real fix is for this function to look for all .md files, + # not for .js files with matching .md file in the same package. + documented_modules.append(["self"]) + return documented_modules + +def module_md_exists(root, module_name): + module_md_path = os.path.join(root, module_name + '.md') + return os.path.exists(module_md_path) + +def tag_wrap(text, tag, attributes={}): + result = '\n<' + tag + for name in attributes.keys(): + result += ' ' + name + '=' + '"' + attributes[name] + '"' + result +='>' + text + '</'+ tag + '>\n' + return result + +def is_high_level(package_json): + return not is_low_level(package_json) + +def is_low_level(package_json): + return 'jetpack-low-level' in package_json.get('keywords', []) + +def insert_after(target, insertion_point_id, text_to_insert): + insertion_point = target.find(insertion_point_id) + len(insertion_point_id) + return target[:insertion_point] + text_to_insert + target[insertion_point:] + +class WebDocs(object): + def __init__(self, root, base_url = '/'): + self.root = root + self.pkg_cfg = packaging.build_pkg_cfg(root) + self.packages_json = packaging.build_pkg_index(self.pkg_cfg) + self.base_page = self._create_base_page(root, base_url) + + def create_guide_page(self, path): + path, ext = os.path.splitext(path) + md_path = path + '.md' + md_content = unicode(open(md_path, 'r').read(), 'utf8') + guide_content = markdown.markdown(md_content) + return self._create_page(guide_content) + + def create_module_page(self, path): + path, ext = os.path.splitext(path) + md_path = path + '.md' + module_content = apirenderer.md_to_div(md_path) + return self._create_page(module_content) + + def create_package_page(self, package_name): + package_content = self._create_package_detail(package_name) + return self._create_page(package_content) + + def _create_page(self, page_content): + page = self._insert_title(self.base_page, page_content) + page = insert_after(page, CONTENT_ID, page_content) + return page.encode('utf8') + + def _create_module_list(self, package_json): + package_name = package_json['name'] + libs = package_json['files'][1]['lib'][1] + doc_path = package_json.get('doc', None) + if not doc_path: + return '' + modules = get_documented_modules(package_name, libs, doc_path) + modules.sort() + module_items = '' + relative_doc_path = doc_path[len(self.root) + 1:] + relative_doc_URL = "/".join(relative_doc_path.split(os.sep)) + for module in modules: + module_link = tag_wrap('/'.join(module), 'a', \ + {'href': relative_doc_URL + '/' + '/'.join(module) + '.html'}) + module_items += tag_wrap(module_link, 'li', {'class':'module'}) + return tag_wrap(module_items, 'ul', {'class':'modules'}) + + def _create_package_summaries(self, packages_json, include): + packages = '' + for package_name in packages_json.keys(): + package_json = packages_json[package_name] + if not include(package_json): + continue + package_path = self.pkg_cfg["packages"][package_name]["root_dir"] + package_directory = package_path[len(self.root) + 1:] + package_directory = "/".join(package_directory.split(os.sep)) + package_link = tag_wrap(package_name, 'a', {'href': \ + package_directory + "/" \ + + package_name + '.html'}) + text = tag_wrap(package_link, 'h4') + text += self._create_module_list(package_json) + packages += tag_wrap(text, 'div', {'class':'package-summary', \ + 'style':'display: block;'}) + return packages + + def _create_base_page(self, root, base_url): + base_page = unicode(open(root + INDEX_PAGE, 'r').read(), 'utf8') + base_tag = 'href="' + base_url + '"' + base_page = insert_after(base_page, BASE_URL_INSERTION_POINT, base_tag) + sdk_version = get_versions()["version"] + base_page = insert_after(base_page, VERSION_INSERTION_POINT, "Version " + sdk_version) + high_level_summaries = \ + self._create_package_summaries(self.packages_json, is_high_level) + base_page = insert_after(base_page, \ + HIGH_LEVEL_PACKAGE_SUMMARIES, high_level_summaries) + low_level_summaries = \ + self._create_package_summaries(self.packages_json, is_low_level) + base_page = insert_after(base_page, \ + LOW_LEVEL_PACKAGE_SUMMARIES, low_level_summaries) + return base_page + + def _create_package_detail_row(self, field_value, \ + field_descriptor, field_name): + meta = tag_wrap(tag_wrap(field_descriptor, 'span', \ + {'class':'meta-header'}), 'td') + value = tag_wrap(tag_wrap(field_value, 'span', \ + {'class':field_name}), 'td') + return tag_wrap(meta + value, 'tr') + + def _create_package_detail_table(self, package_json): + table_contents = '' + if package_json.get('author', None): + table_contents += self._create_package_detail_row(\ + cgi.escape(package_json['author']), 'Author', 'author') + if package_json.get('version', None): + table_contents += self._create_package_detail_row(\ + package_json['version'], 'Version', 'version') + if package_json.get('license', None): + table_contents += self._create_package_detail_row(\ + package_json['license'], 'License', 'license') + if package_json.get('dependencies', None): + table_contents += self._create_package_detail_row(\ + ', '.join(package_json['dependencies']), \ + 'Dependencies', 'dependencies') + table_contents += self._create_package_detail_row(\ + self._create_module_list(package_json), 'Modules', 'modules') + return tag_wrap(tag_wrap(table_contents, 'tbody'), 'table', \ + {'class':'meta-table'}) + + def _create_package_detail(self, package_name): + package_json = self.packages_json.get(package_name, None) + if not package_json: + raise IOError(errno.ENOENT, 'Package not found') + # pieces of the package detail: 1) title, 2) table, 3) description + package_title = tag_wrap(package_name, 'h1') + table = self._create_package_detail_table(package_json) + description = '' + if package_json.get('readme', None): + description += tag_wrap(tag_wrap(\ + markdown.markdown(\ + package_json['readme']), 'p'), 'div', {'class':'docs'}) + return tag_wrap(package_title + table + description, 'div', \ + {'class':'package-detail'}) + + def _insert_title(self, target, content): + match = re.search('<h1>.*</h1>', content) + if match: + title = match.group(0)[len('<h1>'):-len('</h1>')] + ' - ' + \ + DEFAULT_TITLE + else: + title = DEFAULT_TITLE + target = insert_after(target, TITLE_ID, title) + return target |