diff options
Diffstat (limited to 'tools/addon-sdk-1.5/python-lib/cuddlefish/docs')
6 files changed, 0 insertions, 1385 deletions
diff --git a/tools/addon-sdk-1.5/python-lib/cuddlefish/docs/__init__.py b/tools/addon-sdk-1.5/python-lib/cuddlefish/docs/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/tools/addon-sdk-1.5/python-lib/cuddlefish/docs/__init__.py +++ /dev/null diff --git a/tools/addon-sdk-1.5/python-lib/cuddlefish/docs/apiparser.py b/tools/addon-sdk-1.5/python-lib/cuddlefish/docs/apiparser.py deleted file mode 100644 index b6ccf22..0000000 --- a/tools/addon-sdk-1.5/python-lib/cuddlefish/docs/apiparser.py +++ /dev/null @@ -1,392 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -import sys, re, textwrap - -VERSION = 4 - -class ParseError(Exception): - # args[1] is the line number that caused the problem - def __init__(self, why, lineno): - self.why = why - self.lineno = lineno - def __str__(self): - return ("ParseError: the JS API docs were unparseable on line %d: %s" % - (self.lineno, self.why)) - -class Accumulator: - def __init__(self, holder, firstline): - self.holder = holder - self.firstline = firstline - self.otherlines = [] - def addline(self, line): - self.otherlines.append(line) - def finish(self): - # take a list of strings like: - # "initial stuff" (this is in firstline) - # " more stuff" (this is in lines[0]) - # " yet more stuff" - # " indented block" - # " indented block" - # " nonindented stuff" (lines[-1]) - # - # calculate the indentation level by looking at all but the first - # line, and removing the whitespace they all have in common. Then - # join the results with newlines and return a single string. - pieces = [] - if self.firstline: - pieces.append(self.firstline) - if self.otherlines: - pieces.append(textwrap.dedent("\n".join(self.otherlines))) - self.holder["description"] = "\n".join(pieces) - - -class APIParser: - def parse(self, lines, lineno): - api = {"line_number": lineno + 1} -# assign the name from the first line, of the form "<api name="API_NAME">" - title_line = lines[lineno].rstrip("\n") - api["name"] = self._parse_title_line(title_line, lineno + 1) - lineno += 1 -# finished with the first line, assigned the name - working_set = self._initialize_working_set() - props = [] - currentPropHolder = api -# fetch the next line, of the form "@tag [name] {datatype} description" -# and parse it into tag, info, description - tag, info, firstline = self._parseTypeLine(lines[lineno], lineno + 1) - api["type"] = tag -# if this API element is a property then datatype must be set - if tag == 'property': - api['datatype'] = info['datatype'] - # info is ignored - currentAccumulator = Accumulator(api, firstline) - lineno += 1 - while (lineno) < len(lines): - line = lines[lineno].rstrip("\n") - # accumulate any multiline descriptive text belonging to - # the preceding "@" section - if self._is_description_line(line): - currentAccumulator.addline(line) - else: - currentAccumulator.finish() - if line.startswith("<api"): - # then we should recursively handle a nested element - nested_api, lineno = self.parse(lines, lineno) - self._update_working_set(nested_api, working_set) - elif line.startswith("</api"): - # then we have finished parsing this api element - currentAccumulator.finish() - if props and currentPropHolder: - currentPropHolder["props"] = props - self._assemble_api_element(api, working_set) - return api, lineno - else: - # then we are looking at a subcomponent of an <api> element - tag, info, desc = self._parseTypeLine(line, lineno + 1) - currentAccumulator = Accumulator(info, desc) - if tag == "prop": - # build up props[] - props.append(info) - elif tag == "returns": - # close off the @prop list - if props and currentPropHolder: - currentPropHolder["props"] = props - props = [] - api["returns"] = info - currentPropHolder = info - elif tag == "param": - # close off the @prop list - if props and currentPropHolder: - currentPropHolder["props"] = props - props = [] - working_set["params"].append(info) - currentPropHolder = info - elif tag == "argument": - # close off the @prop list - if props and currentPropHolder: - currentPropHolder["props"] = props - props = [] - working_set["arguments"].append(info) - currentPropHolder = info - else: - raise ParseError("unknown '@' section header %s in \ - '%s'" % (tag, line), lineno + 1) - lineno += 1 - raise ParseError("closing </api> tag not found for <api name=\"" + - api["name"] + "\">", lineno + 1) - - def _parse_title_line(self, title_line, lineno): - if "name" not in title_line: - raise ParseError("Opening <api> tag must have a name attribute.", - lineno) - m = re.search("name=['\"]{0,1}([-\w\.]*?)['\"]", title_line) - if not m: - raise ParseError("No value for name attribute found in " - "opening <api> tag.", lineno) - return m.group(1) - - def _is_description_line(self, line): - return not ( (line.lstrip().startswith("@")) or - (line.lstrip().startswith("<api")) or - (line.lstrip().startswith("</api")) ) - - def _initialize_working_set(self): - # working_set accumulates api elements - # that might belong to a parent api element - working_set = {} - working_set["constructors"] = [] - working_set["methods"] = [] - working_set["properties"] = [] - working_set["params"] = [] - working_set["events"] = [] - working_set["arguments"] = [] - return working_set - - def _update_working_set(self, nested_api, working_set): - # add this api element to whichever list is appropriate - if nested_api["type"] == "constructor": - working_set["constructors"].append(nested_api) - if nested_api["type"] == "method": - working_set["methods"].append(nested_api) - if nested_api["type"] == "property": - working_set["properties"].append(nested_api) - if nested_api["type"] == "event": - working_set["events"].append(nested_api) - - def _assemble_signature(self, api_element, params): - signature = api_element["name"] + "(" - if len(params) > 0: - signature += params[0]["name"] - for param in params[1:]: - signature += ", " + param["name"] - signature += ")" - api_element["signature"] = signature - - def _assemble_api_element(self, api_element, working_set): - # if any of this working set's lists are non-empty, - # add it to the current api element - if (api_element["type"] == "constructor") or \ - (api_element["type"] == "function") or \ - (api_element["type"] == "method"): - self._assemble_signature(api_element, working_set["params"]) - if len(working_set["params"]) > 0: - api_element["params"] = working_set["params"] - if len(working_set["properties"]) > 0: - api_element["properties"] = working_set["properties"] - if len(working_set["constructors"]) > 0: - api_element["constructors"] = working_set["constructors"] - if len(working_set["methods"]) > 0: - api_element["methods"] = working_set["methods"] - if len(working_set["events"]) > 0: - api_element["events"] = working_set["events"] - if len(working_set["arguments"]) > 0: - api_element["arguments"] = working_set["arguments"] - - def _validate_info(self, tag, info, line, lineno): - if tag == 'property': - if not 'datatype' in info: - raise ParseError("No type found for @property.", lineno) - elif tag == "param": - if info.get("required", False) and "default" in info: - raise ParseError( - "required parameters should not have defaults: '%s'" - % line, lineno) - elif tag == "prop": - if "datatype" not in info: - raise ParseError("@prop lines must include {type}: '%s'" % - line, lineno) - if "name" not in info: - raise ParseError("@prop lines must provide a name: '%s'" % - line, lineno) - - def _parseTypeLine(self, line, lineno): - # handle these things: - # @method - # @returns description - # @returns {string} description - # @param NAME {type} description - # @param NAME - # @prop NAME {type} description - # @prop NAME - # returns: - # tag: type of api element - # info: linenumber, required, default, name, datatype - # description - - info = {"line_number": lineno} - line = line.rstrip("\n") - pieces = line.split() - - if not pieces: - raise ParseError("line is too short: '%s'" % line, lineno) - if not pieces[0].startswith("@"): - raise ParseError("type line should start with @: '%s'" % line, - lineno) - tag = pieces[0][1:] - skip = 1 - - expect_name = tag in ("param", "prop") - - if len(pieces) == 1: - description = "" - else: - if pieces[1].startswith("{"): - # NAME is missing, pieces[1] is TYPE - pass - else: - if expect_name: - info["required"] = not pieces[1].startswith("[") - name = pieces[1].strip("[ ]") - if "=" in name: - name, info["default"] = name.split("=") - info["name"] = name - skip += 1 - - if len(pieces) > skip and pieces[skip].startswith("{"): - info["datatype"] = pieces[skip].strip("{ }") - skip += 1 - - # we've got the metadata, now extract the description - pieces = line.split(None, skip) - if len(pieces) > skip: - description = pieces[skip] - else: - description = "" - self._validate_info(tag, info, line, lineno) - return tag, info, description - -def parse_hunks(text): - # return a list of tuples. Each is one of: - # ("raw", string) : non-API blocks - # ("api-json", dict) : API blocks - yield ("version", VERSION) - lines = text.splitlines(True) - line_number = 0 - markdown_string = "" - while line_number < len(lines): - line = lines[line_number] - if line.startswith("<api"): - if len(markdown_string) > 0: - yield ("markdown", markdown_string) - markdown_string = "" - api, line_number = APIParser().parse(lines, line_number) - # this business with 'leftover' is a horrible thing to do, - # and exists only to collect the \n after the closing /api tag. - # It's not needed probably, except to help keep compatibility - # with the previous behaviour - leftover = lines[line_number].lstrip("</api>") - if len(leftover) > 0: - markdown_string += leftover - line_number = line_number + 1 - yield ("api-json", api) - else: - markdown_string += line - line_number = line_number + 1 - if len(markdown_string) > 0: - yield ("markdown", markdown_string) - -class TestRenderer: - # render docs for test purposes - - def getm(self, d, key): - return d.get(key, "<MISSING>") - - def join_lines(self, text): - return " ".join([line.strip() for line in text.split("\n")]) - - def render_prop(self, p): - s = "props[%s]: " % self.getm(p, "name") - pieces = [] - for k in ("type", "description", "required", "default"): - if k in p: - pieces.append("%s=%s" % (k, self.join_lines(str(p[k])))) - return s + ", ".join(pieces) - - def render_param(self, p): - pieces = [] - for k in ("name", "type", "description", "required", "default"): - if k in p: - pieces.append("%s=%s" % (k, self.join_lines(str(p[k])))) - yield ", ".join(pieces) - for prop in p.get("props", []): - yield " " + self.render_prop(prop) - - def render_method(self, method): - yield "name= %s" % self.getm(method, "name") - yield "type= %s" % self.getm(method, "type") - yield "description= %s" % self.getm(method, "description") - signature = method.get("signature") - if signature: - yield "signature= %s" % self.getm(method, "signature") - params = method.get("params", []) - if params: - yield "parameters:" - for p in params: - for pline in self.render_param(p): - yield " " + pline - r = method.get("returns", None) - if r: - yield "returns:" - if "type" in r: - yield " type= %s" % r["type"] - if "description" in r: - yield " description= %s" % self.join_lines(r["description"]) - props = r.get("props", []) - for p in props: - yield " " + self.render_prop(p) - - def format_api(self, api): - for mline in self.render_method(api): - yield mline - constructors = api.get("constructors", []) - if constructors: - yield "constructors:" - for m in constructors: - for mline in self.render_method(m): - yield " " + mline - methods = api.get("methods", []) - if methods: - yield "methods:" - for m in methods: - for mline in self.render_method(m): - yield " " + mline - properties = api.get("properties", []) - if properties: - yield "properties:" - for p in properties: - yield " " + self.render_prop(p) - - def render_docs(self, docs_json, outf=sys.stdout): - - for (t,data) in docs_json: - if t == "api-json": - for line in self.format_api(data): - line = line.rstrip("\n") - outf.write("API: " + line + "\n") - else: - for line in str(data).split("\n"): - outf.write("MD :" + line + "\n") - -def hunks_to_dict(docs_json): - exports = {} - for (t,data) in docs_json: - if t != "api-json": - continue - if data["name"]: - exports[data["name"]] = data - return exports - -if __name__ == "__main__": - json = False - if sys.argv[1] == "--json": - json = True - del sys.argv[1] - docs_text = open(sys.argv[1]).read() - docs_parsed = list(parse_hunks(docs_text)) - if json: - import simplejson - print simplejson.dumps(docs_parsed, indent=2) - else: - TestRenderer().render_docs(docs_parsed) diff --git a/tools/addon-sdk-1.5/python-lib/cuddlefish/docs/apirenderer.py b/tools/addon-sdk-1.5/python-lib/cuddlefish/docs/apirenderer.py deleted file mode 100644 index 36e46ef..0000000 --- a/tools/addon-sdk-1.5/python-lib/cuddlefish/docs/apirenderer.py +++ /dev/null @@ -1,302 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -import sys, os -import markdown -import apiparser - -# list of all the 'class' and 'id' attributes assigned to -# <div> and <span> tags by the renderer. -API_REFERENCE = 'api_reference' -MODULE_API_DOCS_CLASS = 'module_api_docs' -MODULE_API_DOCS_ID = '_module_api_docs' -API_HEADER = 'api_header' -API_NAME = 'api_name' -API_COMPONENT_GROUP = 'api_component_group' -API_COMPONENT = 'api_component' -DATATYPE = 'datatype' -RETURNS = 'returns' -PARAMETER_SET = 'parameter_set' -MODULE_DESCRIPTION = 'module_description' - -HTML_HEADER = ''' -<!DOCTYPE html>\n -<html>\n -<head>\n - <meta http-equiv="Content-type" content="text/html; charset=utf-8" />\n - <base target="_blank"/>\n - <link rel="stylesheet" type="text/css" media="all"\n - href="../../../css/base.css" />\n - <link rel="stylesheet" type="text/css" media="all"\n - href="../../../css/apidocs.css" />\n - <title>Add-on SDK Documentation</title>\n - <style type="text/css">\n - body {\n - border: 50px solid #FFFFFF;\n - }\n - </style>\n -\n - <script type="text/javascript">\n - function rewrite_links() {\n - var images = document.getElementsByTagName("img");\n - for (var i = 0; i < images.length; i++) {\n - var before = images[i].src.split("packages/")[0];\n - var after = images[i].src.split("/docs")[1];\n - images[i].src = before + after;\n - }\n - }\n - </script>\n -</head>\n -\n -<body onload = "rewrite_links()">\n''' - -HTML_FOOTER = ''' -</body>\n -\n -</html>\n''' - -def indent(text_in): - text_out = '' - lines = text_in.splitlines(True) - indentation_level = 0 - indentation_depth = 2 - for line in lines: - if (line.startswith('<div')): - text_out += ((' ' * indentation_depth) * indentation_level) + line - if not '</div>' in line: - indentation_level += 1 - else: - if (line.startswith('</div>')): - indentation_level -= 1 - text_out += ((' ' * indentation_depth) * indentation_level) + line - return text_out - -def tag_wrap_id(text, classname, id, tag = 'div'): - return ''.join(['\n<'+ tag + ' id="', id, '" class="', \ - classname, '">\n', text + '\n</' + tag +'>\n']) - -def tag_wrap(text, classname, tag = 'div', inline = False): - if inline: - return ''.join(['\n<' + tag + ' class="', classname, '">', \ - text, '</'+ tag + '>\n']) - else: - return ''.join(['\n<' + tag + ' class="', classname, '">', \ - text, '\n</'+ tag + '>\n']) - -def tag_wrap_inline(text, classname, tag = 'div'): - return ''.join(['\n<' + tag + ' class="', classname, '">', \ - text, '</'+ tag + '>\n']) - -def span_wrap(text, classname): - return ''.join(['<span class="', classname, '">', \ - text, '</span>']) - -class API_Renderer(object): - def __init__(self, json, tag): - self.name = json.get('name', None) - self.tag = tag - self.description = json.get('description', '') - self.json = json - - def render_name(self): - raise Exception('not implemented in this class') - - def render_description(self): - return markdown.markdown(self.description) - - def render_subcomponents(self): - raise Exception('not implemented in this class') - - def get_tag(self): - return self.tag - -class Class_Doc(API_Renderer): - def __init__(self, json, tag): - API_Renderer.__init__(self, json, tag) - - def render_name(self): - return self.name - - def render_subcomponents(self): - return render_object_contents(self.json, 'h5', 'h6') - -class Event_Doc(API_Renderer): - def __init__(self, json, tag): - API_Renderer.__init__(self, json, tag) - self.arguments_json = json.get('arguments', None) - - def render_name(self): - return self.name - - def render_subcomponents(self): - if not self.arguments_json: - return '' - text = ''.join([render_comp(Argument_Doc(argument_json, 'div')) \ - for argument_json in self.arguments_json]) - return tag_wrap(text, PARAMETER_SET) - -class Argument_Doc(API_Renderer): - def __init__(self, json, tag): - API_Renderer.__init__(self, json, tag) - self.datatype = json.get('datatype', None) - - def render_name(self): - return span_wrap(self.datatype, DATATYPE) - - def render_subcomponents(self): - return '' - -class Function_Doc(API_Renderer): - def __init__(self, json, tag): - API_Renderer.__init__(self, json, tag) - self.signature = json['signature'] - self.returns = json.get('returns', None) - self.parameters_json = json.get('params', None) - - def render_name(self): - return self.signature - - def render_subcomponents(self): - return self._render_parameters() + self._render_returns() - - def _render_parameters(self): - if not self.parameters_json: - return '' - text = ''.join([render_comp(Parameter_Doc(parameter_json, 'div')) \ - for parameter_json in self.parameters_json]) - return tag_wrap(text, PARAMETER_SET) - - def _render_returns(self): - if not self.returns: - return '' - text = 'Returns: ' + span_wrap(self.returns['datatype'], DATATYPE) - text += markdown.markdown(self.returns['description']) - return tag_wrap(text, RETURNS) - -class Property_Doc(API_Renderer): - def __init__(self, json, tag): - API_Renderer.__init__(self, json, tag) - self.datatype = json.get('datatype', None) - self.required = json.get('required', True) - self.default = json.get('default', False) - - def render_name(self): - rendered = self.name - if self.default: - rendered = rendered + " = " + self.default - if self.datatype: - rendered = rendered + ' : ' + span_wrap(self.datatype, DATATYPE) - if not self.required: - rendered = '[ ' + rendered + ' ]' - return rendered - - def render_subcomponents(self): - return render_object_contents(self.json) - -class Parameter_Doc(Property_Doc): - def __init__(self, json, tag): - Property_Doc.__init__(self, json, tag) - self.properties_json = json.get('props', None) - - def render_subcomponents(self): - if not self.properties_json: - return '' - text = ''.join([render_comp(Property_Doc(property_json, 'div')) \ - for property_json in self.properties_json]) - return text - -def render_object_contents(json, tag = 'div', comp_tag = 'div'): - ctors = json.get('constructors', None) - text = render_comp_group(ctors, 'Constructors', Function_Doc, tag, comp_tag) - methods = json.get('methods', None) - text += render_comp_group(methods, 'Methods', Function_Doc, tag, comp_tag) - properties = json.get('properties', None) - text += render_comp_group(properties, 'Properties', Property_Doc, tag, comp_tag) - events = json.get('events', None) - text += render_comp_group(events, 'Events', Event_Doc, tag, comp_tag) - return text - -def render_comp(component): - # a component is wrapped inside a single div marked 'API_COMPONENT' - # containing: - # 1) the component name, marked 'API_NAME' - text = tag_wrap(component.render_name(), API_NAME, component.get_tag(), True) - # 2) the component description - text += component.render_description() - # 3) the component contents - text += component.render_subcomponents() - return tag_wrap(text, API_COMPONENT) - -def render_comp_group(group, group_name, ctor, tag = 'div', comp_tag = 'div'): - if not group: - return '' - # component group is a list of components in a single div called - # 'API_COMPONENT_GROUP' containing: - # 1) a title for the group marked with 'API_HEADER' - text = tag_wrap(group_name, API_HEADER, tag, True) - # 2) each component - text += ''.join([render_comp(ctor(api, comp_tag)) for api in group]) - return tag_wrap(text, API_COMPONENT_GROUP) - -def render_descriptions(descriptions_md): - text = ''.join([description_md for description_md in descriptions_md]) - return tag_wrap(markdown.markdown(text), MODULE_DESCRIPTION) - -def render_api_reference(api_docs): - if (len(api_docs) == 0): - return '' - # at the top level api reference is in a single div marked 'API_REFERENCE', - # containing: - # 1) a title 'API Reference' marked with 'API_HEADER' - text = tag_wrap('API Reference', API_HEADER, 'h2', True) - # 2) a component group called 'Classes' containing any class elements - classes = [api for api in api_docs if api['type'] == 'class'] - text += render_comp_group(classes, 'Classes', Class_Doc, 'h3', 'h4') - # 3) a component group called 'Functions' containing any global functions - functions = [api for api in api_docs if api['type'] == 'function'] - text += render_comp_group(functions, 'Functions', Function_Doc, 'h3', 'h4') - # 4) a component group called 'Properties' containing any global properties - properties = [api for api in api_docs if api['type'] == 'property'] - text += render_comp_group(properties, 'Properties', Property_Doc, 'h3', 'h4') - # 5) a component group called 'Events' containing any global events - events = [api for api in api_docs if api['type'] == 'event'] - text += render_comp_group(events, 'Events', Event_Doc, 'h3', 'h4') - return tag_wrap(text, API_REFERENCE) - -# take the JSON output of apiparser -# return the HTML DIV containing the rendered component -def json_to_div(json, markdown_filename): - module_name, ext = os.path.splitext(os.path.basename(markdown_filename)) - descriptions = [hunk[1] for hunk in json if hunk[0]=='markdown'] - api_docs = [hunk[1] for hunk in json if hunk[0]=='api-json'] - text = "<h1>" + module_name + "</h1>" - text += render_descriptions(descriptions) - text += render_api_reference(api_docs) - text = tag_wrap_id(text, MODULE_API_DOCS_CLASS, \ - module_name + MODULE_API_DOCS_ID) - return text.encode('utf8') - -# take the JSON output of apiparser -# return standalone HTML containing the rendered component -def json_to_html(json, markdown_filename): - return indent(HTML_HEADER + \ - json_to_div(json, markdown_filename) + HTML_FOOTER) - -# take the name of a Markdown file -# return the HTML DIV containing the rendered component -def md_to_div(markdown_filename): - markdown_contents = open(markdown_filename).read().decode('utf8') - json = list(apiparser.parse_hunks(markdown_contents)) - return json_to_div(json, markdown_filename) - -# take the name of a Markdown file -# return standalone HTML containing the rendered component -def md_to_html(markdown_filename): - return indent(HTML_HEADER + md_to_div(markdown_filename) + HTML_FOOTER) - -if __name__ == '__main__': - if (len(sys.argv) == 0): - print 'Supply the name of a docs file to parse' - else: - print md_to_html(sys.argv[1]) diff --git a/tools/addon-sdk-1.5/python-lib/cuddlefish/docs/generate.py b/tools/addon-sdk-1.5/python-lib/cuddlefish/docs/generate.py deleted file mode 100644 index 789a8dd..0000000 --- a/tools/addon-sdk-1.5/python-lib/cuddlefish/docs/generate.py +++ /dev/null @@ -1,283 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -import os -import sys -import shutil -import hashlib -import tarfile -import StringIO -import HTMLParser -import urlparse - -from cuddlefish import packaging -from cuddlefish.docs import apiparser -from cuddlefish.docs import apirenderer -from cuddlefish.docs import webdocs -import simplejson as json - -DIGEST = "status.md5" -TGZ_FILENAME = "addon-sdk-docs.tgz" - -def get_sdk_docs_path(env_root): - return os.path.join(env_root, "doc") - -def get_base_url(env_root): - sdk_docs_path = get_sdk_docs_path(env_root).lstrip("/") - return "file://"+"/"+"/".join(sdk_docs_path.split(os.sep))+"/" - -def clean_generated_docs(docs_dir): - status_file = os.path.join(docs_dir, "status.md5") - if os.path.exists(status_file): - os.remove(status_file) - 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): - clean_generated_docs(get_sdk_docs_path(env_root)) - generate_docs(env_root, stdout=StringIO.StringIO()) - tgz = tarfile.open(TGZ_FILENAME, 'w:gz') - tgz.add(get_sdk_docs_path(env_root), "doc") - tgz.close() - return TGZ_FILENAME - -def generate_local_docs(env_root): - return generate_docs(env_root, get_base_url(env_root)) - -def generate_named_file(env_root, filename): - web_docs = webdocs.WebDocs(env_root, get_base_url(env_root)) - # next, generate api doc or guide doc - abs_path = os.path.abspath(filename) - if abs_path.startswith(os.path.join(env_root, 'packages')): - doc_html, dest_dir, filename = generate_api_doc(env_root, abs_path, web_docs) - write_file(env_root, doc_html, dest_dir, filename) - elif abs_path.startswith(os.path.join(get_sdk_docs_path(env_root), 'dev-guide-source')): - doc_html, dest_dir, filename = generate_guide_doc(env_root, abs_path, web_docs) - write_file(env_root, doc_html, dest_dir, filename, False) - else: - raise ValueError("Not a valid path to a documentation file") - -def generate_docs(env_root, base_url=None, stdout=sys.stdout): - docs_dir = get_sdk_docs_path(env_root) - # if the generated docs don't exist, generate everything - if not os.path.exists(os.path.join(docs_dir, "dev-guide")): - print >>stdout, "Generating documentation..." - generate_docs_from_scratch(env_root, base_url) - current_status = calculate_current_status(env_root) - open(os.path.join(docs_dir, DIGEST), "w").write(current_status) - else: - current_status = calculate_current_status(env_root) - previous_status_file = os.path.join(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..." - generate_docs_from_scratch(env_root, base_url) - open(os.path.join(docs_dir, DIGEST), "w").write(current_status) - return get_base_url(env_root) + "index.html" - -# 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): - docs_dir = get_sdk_docs_path(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(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)))) - base_html_file = os.path.join(docs_dir, "static-files", "base.html") - current_status.update(base_html_file) - current_status.update(str(os.path.getmtime(os.path.join(dirpath, base_html_file)))) - return current_status.digest() - -def generate_docs_from_scratch(env_root, base_url): - docs_dir = get_sdk_docs_path(env_root) - web_docs = webdocs.WebDocs(env_root, base_url) - must_rewrite_links = True - if base_url: - must_rewrite_links = False - 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 - package_dirname = os.path.basename(src_dir) - dest_dir = os.path.join(docs_dir, "packages", package_dirname) - 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(pkg_name) - replace_file(env_root, package_filename, package_doc_html, must_rewrite_links) - - # 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, must_rewrite_links) - - # generate all the guide docs - dev_guide_src = os.path.join(docs_dir, "dev-guide-source") - generate_file_tree(env_root, dev_guide_src, web_docs, generate_guide_doc, must_rewrite_links) - - # make /md/dev-guide/welcome.html the top level index file - doc_html, dest_dir, filename = generate_guide_doc(env_root, os.path.join(docs_dir, 'dev-guide-source', 'welcome.md'), web_docs) - write_file(env_root, doc_html, docs_dir, 'index', False) - -def generate_file_tree(env_root, src_dir, web_docs, generate_file, must_rewrite_links): - 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) - if src_path.endswith(".md"): - # write the standalone HTML files - doc_html, dest_dir, filename = generate_file(env_root, src_path, web_docs) - write_file(env_root, doc_html, dest_dir, filename, must_rewrite_links) - -def generate_api_doc(env_root, src_dir, web_docs): - doc_html = web_docs.create_module_page(src_dir) - dest_dir, filename = get_api_doc_dest_path(env_root, src_dir) - return doc_html, dest_dir, filename - -def generate_guide_doc(env_root, src_dir, web_docs): - doc_html = web_docs.create_guide_page(src_dir) - dest_dir, filename = get_guide_doc_dest_path(env_root, src_dir) - return doc_html, dest_dir, filename - -def write_file(env_root, doc_html, dest_dir, filename, must_rewrite_links): - if not os.path.exists(dest_dir): - os.makedirs(dest_dir) - dest_path_html = os.path.join(dest_dir, filename) + ".html" - replace_file(env_root, dest_path_html, doc_html, must_rewrite_links) - return dest_path_html - -def replace_file(env_root, dest_path, file_contents, must_rewrite_links): - if os.path.exists(dest_path): - os.remove(dest_path) - # before we copy the final version, we'll rewrite the links - # I'll do this last, just because we know definitely what the dest_path is at this point - if must_rewrite_links and dest_path.endswith(".html"): - file_contents = rewrite_links(env_root, file_contents, dest_path) - open(dest_path, "w").write(file_contents) - -def rewrite_links(env_root, page, dest_path): - dest_path_depth = len(dest_path.split(os.sep)) -1 # because dest_path includes filename - docs_root_depth = len(get_sdk_docs_path(env_root).split(os.sep)) - relative_depth = dest_path_depth - docs_root_depth - linkRewriter = LinkRewriter("../" * relative_depth) - return linkRewriter.rewrite_links(page) - -# 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(get_sdk_docs_path(env_root), "dev-guide-source")) + 1:] - return os.path.split(os.path.join(get_sdk_docs_path(env_root), "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(get_sdk_docs_path(env_root), src_dir_relative)[:-3]) - -class LinkRewriter(HTMLParser.HTMLParser): - def __init__(self, link_prefix): - HTMLParser.HTMLParser.__init__(self) - self.stack = [] - self.link_prefix = link_prefix - - def rewrite_links(self, page): - self.feed(page) - self.close() - page = ''.join(self.stack) - self.stack = [] - return page - - def handle_decl(self, decl): - self.stack.append("<!" + decl + ">") - - def handle_comment(self, decl): - self.stack.append("<!--" + decl + "-->") - - def handle_starttag(self, tag, attrs): - attrs = dict(attrs) - href = attrs.get('href', '') - if href: - parsed = urlparse.urlparse(href) - if not parsed.scheme: - attrs['href'] = self.link_prefix + href - src = attrs.get('src', '') - if src: - parsed = urlparse.urlparse(src) - if not parsed.scheme: - attrs['src'] = self.link_prefix + src - self.stack.append(self.__html_start_tag(tag, attrs)) - - def handle_endtag(self, tag): - self.stack.append(self.__html_end_tag(tag)) - - def handle_startendtag(self, tag, attrs): - self.stack.append(self.__html_startend_tag(tag, attrs)) - - def handle_data(self, data): - self.stack.append(data) - - def __html_start_tag(self, tag, attrs): - return '<%s%s>' % (tag, self.__html_attrs(attrs)) - - def __html_startend_tag(self, tag, attrs): - return '<%s%s/>' % (tag, self.__html_attrs(attrs)) - - def __html_end_tag(self, tag): - return '</%s>' % (tag) - - def __html_attrs(self, attrs): - _attrs = '' - if attrs: - _attrs = ' %s' % (' '.join([('%s="%s"' % (k,v)) for k,v in dict(attrs).iteritems()])) - return _attrs diff --git a/tools/addon-sdk-1.5/python-lib/cuddlefish/docs/renderapi.readme.md b/tools/addon-sdk-1.5/python-lib/cuddlefish/docs/renderapi.readme.md deleted file mode 100644 index 627c2a6..0000000 --- a/tools/addon-sdk-1.5/python-lib/cuddlefish/docs/renderapi.readme.md +++ /dev/null @@ -1,210 +0,0 @@ -<!-- This Source Code Form is subject to the terms of the Mozilla Public - - License, v. 2.0. If a copy of the MPL was not distributed with this - - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - - -This document describes the structure of the HTML generated by the renderapi.py -tool, both for use in the API docs shown by "cfx docs" and as exported by -"cfx sdocs". The particular HTML id and class attributes embedded in the files, -as well as their organization, represent the interface between the tool and any -front-end code wanting to style the docs in some particular way. - -renderapi generates two sorts of files: - -- a file called "<module-name>.div": this is the contents of the parsed -Markdown file rendered inside a well-defined DIV tag - -- a file called "<module-name>.html": this is the DIV from above inserted into -a simple HTML template that references a sample CSS file which styles the -contents of the DIV. This CSS file is the same as the one used by the SDK -itself. - -DIV tags --------- -The following class and id attributes are used in the DIV: - -renderapi uses a number of class attributes and a single id attribute in the DIV: - -id attribute <module_name>"_module_api_docs" -class attribute "api_reference" -class attribute "module_api_docs" -class attribute "api_header" -class attribute "api_name" -class attribute "api_component_group" -class attribute "api_component" -class attribute "datatype" -class attribute "returns" -class attribute "parameter_set" -class attribute "module_description" - -DIV structure -------------- -The top level DIV is marked with the id attribute and the "module_api_docs" class -attribute: - - <div id='tabs_module_api_docs' class='module_api_docs'> - //module doc contents - </div> - - -Inside this: - -- the first item is an <h1> heading containing the name of the module: - -- all "markdown" hunks (that is, all descriptive text not occurring -inside <api></api> tags) are rendered inside a DIV marked with the -"module-description" class attribute - -- all <api></api> content is rendered, enclosed in a single tag marked -with the "api_reference" class attribute: - - <div id='tabs_module_api_docs' class='module_api_docs'> - <div class='module_description'> - //descriptions - </div> - <div class='api_reference'> - //api reference - </div> - </div> - -If there is no <api></api> content, then the "api-reference" section is absent. - -### API Reference structure ### - -The first item in API reference is an <h2> heading title marked with the -"api_header" attribute. This might have the text content "API Reference" -(but you should not rely on that): - - <div class='api_reference'> - - <h2 class='api_header'>API Reference</h2> - - //api contents - - </div> - -After the title come one or more component groups. - -#### Component Group #### - -A component group is marked with the "api_component_group" attribute. The -component group is a collection of some sort of component: for example, a group -of classes, a group of functions, or a group of events. - -Each component group starts off with a header marked with the -"api_header" attribute and is followed by one or more sections marked with the -"api_component" attribute. -At the top level (that is, when they are directly under the "API Reference" -heading), the "api_header" items are <h3> headings, otherwise they are divs. - - <div class='api_reference'> - - <h2 class='api_header'>API Reference</h2> - - <div class='api_component_group'> - - <h3 class='api_header'>Classes</h3> - - <div class='api_component'> - // the first class - </div> - - <div class='api_component'> - // another class - </div> - - </div> - - <div class='api_component_group'> - //some different components - - <h3 class='api_header'>Functions</h3> - - <div class='api_component'> - the first function - </div> - - <div class='api_component'> - another function - </div> - - </div> - - </div> - -#### Component #### - -API components represent actual objects in the API like classes, functions, -properties and events. - -Each component starts with a section marked with the -"api_name" tag, which includes the name of the component in the API: for -example "postMessage(message)". - -Components at the top level (i.e., directly under h3 headings) are <h4> -headings, otherwise they are divs. - -After the name, the component's contents are listed. Different sorts of -components may have different sorts of contents: for example, a function might -have parameters. If the component is composite then it may contain its own -component group. For example, a class may contain methods and properties, -which might be grouped together. - - <div class='api_component'> - - <h4 class='api_name'>Panel</h4> - - <div class='api_component_group'> - - <div class='api_header'> - Methods - </div> - - <div class='api_component'> - show() - </div> - - </div> - - </div> - -Other attributes ------------------------------ - -### Datatype ### -All primitive data types, like "string" and "number", are marked with the -"datatype" class attribute: - - <div class="api_component"> - - <div class="api_name"> - label : <span class="datatype">string</span> - </div> - - <p>A required string description of the widget used for accessibility, - title bars, and error reporting.</p> - - </div> - -### Returns ### - -Functions mark return values with the "returns" class attribute. - - <div class="api_component"> - - <div class="api_name"> - get() - </div> - - Make a `GET` request. - - <div class="returns"> - Returns: <span class="datatype">Request</span> - </div> - - </div> - -### Parameter_set ### - -Functions that take parameters mark them with the parameter_set class -attribute. diff --git a/tools/addon-sdk-1.5/python-lib/cuddlefish/docs/webdocs.py b/tools/addon-sdk-1.5/python-lib/cuddlefish/docs/webdocs.py deleted file mode 100644 index 44f68a5..0000000 --- a/tools/addon-sdk-1.5/python-lib/cuddlefish/docs/webdocs.py +++ /dev/null @@ -1,198 +0,0 @@ -import os, re, errno -import markdown -import cgi - -from cuddlefish import packaging -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 = None): - 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') - if base_url: - 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 |