From b14ff1002f53c24054960ede321090282644c4dc Mon Sep 17 00:00:00 2001 From: "David Z. Chen" Date: Wed, 16 Nov 2016 13:48:20 -0800 Subject: [PATCH] Implement generating overview page. (#30) This change adds a new feature to generate an overview page for all of the rule sets in the generated documentation. This is particularly useful for HTML documentation and allows users to directly drop the generated HTML docs onto a webserver and serve the docs as a standalone website. This change also adds a link_ext attribute, which allows for customizing the file extension used for links in the generated documentation since some webservers serve Markdown pages with the .md file extension rather than .html. Fixes #24 --- skydoc/build.proto | 7 ++ skydoc/macro_extractor.py | 1 + skydoc/macro_extractor_test.py | 6 ++ skydoc/main.py | 101 ++++++++++++++++------- skydoc/rule.py | 33 ++++++-- skydoc/rule_extractor.py | 4 + skydoc/rule_extractor_test.py | 50 +++++++++++ skydoc/sass/main.scss | 20 ++++- skydoc/templates/BUILD | 5 ++ skydoc/templates/html.jinja | 56 +------------ skydoc/templates/html_footer.jinja | 31 +++++++ skydoc/templates/html_header.jinja | 52 ++++++++++++ skydoc/templates/html_overview.jinja | 22 +++++ skydoc/templates/markdown.jinja | 2 +- skydoc/templates/markdown_overview.jinja | 18 ++++ skydoc/templates/nav.jinja | 13 ++- skydoc/templates/overview.jinja | 100 ++++++++++++++++++++++ skylark/BUILD | 1 + skylark/skylark.bzl | 15 ++++ 19 files changed, 441 insertions(+), 96 deletions(-) create mode 100644 skydoc/templates/html_footer.jinja create mode 100644 skydoc/templates/html_header.jinja create mode 100644 skydoc/templates/html_overview.jinja create mode 100644 skydoc/templates/markdown_overview.jinja create mode 100644 skydoc/templates/overview.jinja diff --git a/skydoc/build.proto b/skydoc/build.proto index b63cbb7..6ee8953 100644 --- a/skydoc/build.proto +++ b/skydoc/build.proto @@ -94,6 +94,13 @@ message RuleDefinition { // The list of outputs for this rule. repeated OutputTarget output = 5; + + enum Type { + RULE = 1; + MACRO = 2; + REPOSITORY_RULE = 3; + } + optional Type type = 6; } message BuildLanguage { diff --git a/skydoc/macro_extractor.py b/skydoc/macro_extractor.py index ab59772..49c70c8 100644 --- a/skydoc/macro_extractor.py +++ b/skydoc/macro_extractor.py @@ -71,6 +71,7 @@ def _add_macro_doc(self, stmt): rule = self.__language.rule.add() rule.name = stmt.name + rule.type = build_pb2.RuleDefinition.MACRO doc = ast.get_docstring(stmt) if doc: diff --git a/skydoc/macro_extractor_test.py b/skydoc/macro_extractor_test.py index cf2a549..f25f02c 100644 --- a/skydoc/macro_extractor_test.py +++ b/skydoc/macro_extractor_test.py @@ -86,6 +86,7 @@ def multiline(name, foo=False, visibility=None): mandatory: false documentation: "The visibility of this rule.\\n\\nDocumentation for visibility continued here." } + type: MACRO } """) @@ -115,6 +116,7 @@ def undocumented(name, visibility=None): type: UNKNOWN mandatory: false } + type: MACRO } """) @@ -167,6 +169,7 @@ def public(name, visibility=None): mandatory: false documentation: "The visibility of this rule." } + type: MACRO } """) @@ -230,6 +233,7 @@ def example_macro(name, foo, visibility=None): mandatory: false documentation: "The visibility of this rule." } + type: MACRO } """) @@ -279,6 +283,7 @@ def macro_with_example(name, foo, visibility=None): mandatory: false documentation: "The visibility of this rule." } + type: MACRO } """) @@ -338,6 +343,7 @@ def macro_with_outputs(name, foo, visibility=None): template: "%{name}.jar" documentation: "A Java archive." } + type: MACRO } """) diff --git a/skydoc/main.py b/skydoc/main.py index f5ceaab..5091756 100755 --- a/skydoc/main.py +++ b/skydoc/main.py @@ -48,6 +48,11 @@ 'generated in subdirectories that match the package structure of the ' 'input .bzl files. The prefix to strip must be common to all .bzl files; ' 'otherwise, skydoc will raise an error.') +gflags.DEFINE_bool('overview', False, 'Whether to generate an overview page') +gflags.DEFINE_string('overview_filename', 'index', + 'The file name to use for the overview page.') +gflags.DEFINE_string('link_ext', 'html', + 'The file extension used for links in the generated documentation') FLAGS = gflags.FLAGS @@ -60,12 +65,13 @@ CSS_FILE = 'main.css' -def _create_jinja_environment(): +def _create_jinja_environment(link_ext): env = jinja2.Environment( loader=jinja2.FileSystemLoader(_runfile_path(TEMPLATE_PATH)), keep_trailing_newline=True, line_statement_prefix='%') env.filters['markdown'] = lambda text: jinja2.Markup(mistune.markdown(text)) + env.filters['link'] = lambda fname: '/' + fname + '.' + link_ext return env @@ -112,14 +118,21 @@ def merge_languages(macro_language, rule_language): new_rule.CopyFrom(rule) return macro_language +class WriterOptions(object): + def __init__(self, output_dir, output_file, output_zip, overview, + overview_filename, link_ext): + self.output_dir = output_dir + self.output_file = output_file + self.output_zip = output_zip + self.overview = overview + self.overview_filename = overview_filename + self.link_ext = link_ext + class MarkdownWriter(object): """Writer for generating documentation in Markdown.""" - def __init__(self, output_dir, output_file, output_zip, strip_prefix): - self.__output_dir = output_dir - self.__output_file = output_file - self.__output_zip = output_zip - self.__strip_prefix = strip_prefix + def __init__(self, writer_options): + self.__options = writer_options def write(self, rulesets): """Write the documentation for the rules contained in rulesets.""" @@ -129,19 +142,21 @@ def write(self, rulesets): for ruleset in rulesets: if len(ruleset.rules) > 0: output_files.append(self._write_ruleset(temp_dir, ruleset)) + if self.__options.overview: + output_files.append(self._write_overview(temp_dir, rulesets)) - if self.__output_zip: + if self.__options.output_zip: # We are generating a zip archive containing all the documentation. # Write each documentation file generated in the temp directory to the # zip file. - with zipfile.ZipFile(self.__output_file, 'w') as zf: + with zipfile.ZipFile(self.__options.output_file, 'w') as zf: for output_file, output_path in output_files: zf.write(output_file, output_path) else: # We are generating documentation in the output_dir directory. Copy each # documentation file to output_dir. for output_file, output_path in output_files: - dest_file = os.path.join(self.__output_dir, output_path) + dest_file = os.path.join(self.__options.output_dir, output_path) dest_dir = os.path.dirname(dest_file) if not os.path.exists(dest_dir): os.makedirs(dest_dir) @@ -153,13 +168,13 @@ def write(self, rulesets): def _write_ruleset(self, output_dir, ruleset): # Load template and render Markdown. - env = _create_jinja_environment() + env = _create_jinja_environment(self.__options.link_ext) template = env.get_template('markdown.jinja') out = template.render(ruleset=ruleset) # Write output to file. Output files are created in a directory structure # that matches that of the input file. - output_path = ruleset.output_filename(self.__strip_prefix, 'md') + output_path = ruleset.output_file + '.md' output_file = "%s/%s" % (output_dir, output_path) file_dirname = os.path.dirname(output_file) if not os.path.exists(file_dirname): @@ -168,20 +183,29 @@ def _write_ruleset(self, output_dir, ruleset): f.write(out) return (output_file, output_path) + def _write_overview(self, output_dir, rulesets): + template = self.__env.get_template('markdown_overview.jinja') + out = template.render(rulesets=rulesets) + + output_file = "%s/%s.md" % (output_dir, self.options.overview_filename) + with open(output_file, "w") as f: + f.write(out) + return (output_file, "%s.md" % self.options.overview_filename) + class HtmlWriter(object): """Writer for generating documentation in HTML.""" - def __init__(self, output_dir, output_file, output_zip, strip_prefix): - self.__output_dir = output_dir - self.__output_file = output_file - self.__output_zip = output_zip - self.__strip_prefix = strip_prefix - self.__env = _create_jinja_environment() + def __init__(self, options): + self.__options = options + self.__env = _create_jinja_environment(self.__options.link_ext) def write(self, rulesets): # Generate navigation used for all rules. nav_template = self.__env.get_template('nav.jinja') - nav = nav_template.render(rulesets=rulesets) + nav = nav_template.render( + rulesets=rulesets, + overview=self.__options.overview, + overview_filename=self.__options.overview_filename) try: temp_dir = tempfile.mkdtemp() @@ -189,16 +213,18 @@ def write(self, rulesets): for ruleset in rulesets: if len(ruleset.rules) > 0: output_files.append(self._write_ruleset(temp_dir, ruleset, nav)) + if self.__options.overview: + output_files.append(self._write_overview(temp_dir, rulesets, nav)) - if self.__output_zip: - with zipfile.ZipFile(self.__output_file, 'w') as zf: + if self.__options.output_zip: + with zipfile.ZipFile(self.__options.output_file, 'w') as zf: for output_file, output_path in output_files: zf.write(output_file, output_path) zf.write(os.path.join(_runfile_path(CSS_PATH), CSS_FILE), '%s' % CSS_FILE) else: for output_file, output_path in output_files: - dest_file = os.path.join(self.__output_dir, output_path) + dest_file = os.path.join(self.__options.output_dir, output_path) dest_dir = os.path.dirname(dest_file) if not os.path.exists(dest_dir): os.makedirs(dest_dir) @@ -206,7 +232,7 @@ def write(self, rulesets): # Copy CSS file. shutil.copyfile(os.path.join(_runfile_path(CSS_PATH), CSS_FILE), - os.path.join(self.__output_dir, CSS_FILE)) + os.path.join(self.__options.output_dir, CSS_FILE)) finally: # Delete temporary directory. shutil.rmtree(temp_dir) @@ -214,11 +240,11 @@ def write(self, rulesets): def _write_ruleset(self, output_dir, ruleset, nav): # Load template and render markdown. template = self.__env.get_template('html.jinja') - out = template.render(ruleset=ruleset, nav=nav) + out = template.render(title=ruleset.title, ruleset=ruleset, nav=nav) # Write output to file. Output files are created in a directory structure # that matches that of the input file. - output_path = ruleset.output_filename(self.__strip_prefix, 'html') + output_path = ruleset.output_file + '.html' output_file = "%s/%s" % (output_dir, output_path) file_dirname = os.path.dirname(output_file) if not os.path.exists(file_dirname): @@ -227,6 +253,15 @@ def _write_ruleset(self, output_dir, ruleset, nav): f.write(out) return (output_file, output_path) + def _write_overview(self, output_dir, rulesets, nav): + template = self.__env.get_template('html_overview.jinja') + out = template.render(title='Overview', rulesets=rulesets, nav=nav) + + output_file = "%s/%s.html" % (output_dir, self.__options.overview_filename) + with open(output_file, "w") as f: + f.write(out) + return (output_file, "%s.html" % self.__options.overview_filename) + def main(argv): if FLAGS.output_dir and FLAGS.output_file: sys.stderr.write('Only one of --output_dir or --output_file can be set.') @@ -252,17 +287,19 @@ def main(argv): rule_doc_extractor.parse_bzl(bzl_file) merged_language = merge_languages(macro_doc_extractor.proto(), rule_doc_extractor.proto()) - rulesets.append(rule.RuleSet(bzl_file, merged_language, - macro_doc_extractor.title, - macro_doc_extractor.description)) - + rulesets.append( + rule.RuleSet(bzl_file, merged_language, macro_doc_extractor.title, + macro_doc_extractor.description, strip_prefix, + FLAGS.format)) + + writer_options = WriterOptions( + FLAGS.output_dir, FLAGS.output_file, FLAGS.zip, FLAGS.overview, + FLAGS.overview_filename, FLAGS.link_ext) if FLAGS.format == "markdown": - markdown_writer = MarkdownWriter(FLAGS.output_dir, FLAGS.output_file, - FLAGS.zip, strip_prefix) + markdown_writer = MarkdownWriter(writer_options) markdown_writer.write(rulesets) elif FLAGS.format == "html": - html_writer = HtmlWriter(FLAGS.output_dir, FLAGS.output_file, FLAGS.zip, - strip_prefix) + html_writer = HtmlWriter(writer_options) html_writer.write(rulesets) else: sys.stderr.write( diff --git a/skydoc/rule.py b/skydoc/rule.py index 8da8696..97b3991 100644 --- a/skydoc/rule.py +++ b/skydoc/rule.py @@ -105,6 +105,7 @@ class Rule(object): def __init__(self, proto): self.__proto = proto self.name = proto.name + self.type = proto.type self.documentation = proto.documentation self.example_documentation = proto.example_documentation self.signature = self._get_signature(proto) @@ -115,6 +116,9 @@ def __init__(self, proto): for output in proto.output: self.outputs.append(Output(output)) + parts = proto.documentation.split("\n\n") + self.short_documentation = parts[0] + def _get_signature(self, proto): """Returns the rule signature for this rule.""" signature = proto.name + '(' @@ -131,18 +135,33 @@ def _get_signature(self, proto): class RuleSet(object): """Representation of a rule set used to render documentation templates.""" - def __init__(self, bzl_file, language, title, description): + def __init__(self, bzl_file, language, title, description, strip_prefix, + format): self.bzl_file = bzl_file file_basename = os.path.basename(bzl_file) self.name = file_basename.replace('.bzl', '') self.language = language self.title = title if title else "%s Rules" % self.name self.description = description - self.rules = [] - for rule_proto in language.rule: - self.rules.append(Rule(rule_proto)) - def output_filename(self, strip_prefix, file_ext): + # Generate output file name. + file_extension = 'html' if format == 'html' else 'md' assert self.bzl_file.startswith(strip_prefix) - output_path = self.bzl_file.replace('.bzl', '.%s' % file_ext) - return output_path[len(strip_prefix):] + output_path = self.bzl_file.replace('.bzl', '') + self.output_file = output_path[len(strip_prefix):] + + # Populate all rules in this ruleset. + self.definitions = [] + self.rules = [] + self.repository_rules = [] + self.macros = [] + for rule_proto in language.rule: + definition = Rule(rule_proto) + self.definitions.append(definition) + if rule_proto.type == build_pb2.RuleDefinition.RULE: + self.rules.append(definition) + elif rule_proto.type == build_pb2.RuleDefinition.MACRO: + self.macros.append(definition) + else: + assert rule_proto.type == build_pb2.RuleDefinition.REPOSITORY_RULE + self.repository_rules.append(definition) diff --git a/skydoc/rule_extractor.py b/skydoc/rule_extractor.py index f2c89f6..cac28d5 100644 --- a/skydoc/rule_extractor.py +++ b/skydoc/rule_extractor.py @@ -146,6 +146,10 @@ def _assemble_protos(self): for rule_desc in rules: rule = self.__language.rule.add() rule.name = rule_desc.name + if rule_desc.type == 'rule': + rule.type = build_pb2.RuleDefinition.RULE + else: + rule.type = build_pb2.RuleDefinition.REPOSITORY_RULE if rule_desc.doc: rule.documentation = rule_desc.doc if rule_desc.example_doc: diff --git a/skydoc/rule_extractor_test.py b/skydoc/rule_extractor_test.py index 668acc5..ede875e 100644 --- a/skydoc/rule_extractor_test.py +++ b/skydoc/rule_extractor_test.py @@ -176,6 +176,7 @@ def impl(ctx): documentation: "A dictionary mapping string to list of string argument." default: "{\'foo\': [\'bar\', \'baz\']}" } + type: RULE } """) @@ -214,6 +215,7 @@ def _impl(ctx): mandatory: false default: "''" } + type: RULE } """) @@ -281,6 +283,7 @@ def _public_impl(ctx): documentation: "A string argument." default: "''" } + type: RULE } """) @@ -336,6 +339,7 @@ def _impl(ctx): mandatory: false documentation: "A label argument.\\n\\nDocumentation for arg_label continued here." } + type: RULE } """) @@ -400,6 +404,7 @@ def example_macro(name, foo, visibility=None): documentation: "A string argument." default: "''" } + type: RULE } """) @@ -453,6 +458,7 @@ def _impl(ctx): documentation: "A string argument." default: "''" } + type: RULE } """) @@ -520,6 +526,7 @@ def _impl(ctx): template: "%{name}.jar" documentation: "A Java archive." } + type: RULE } """) @@ -533,5 +540,48 @@ def test_loads_ignored(self): expected = '' self.check_protos(src, expected) + def test_repository_rule(self): + src = textwrap.dedent("""\ + def _impl(repository_ctx): + return struct() + + repo_rule = repository_rule( + implementation = _impl, + local = True, + attrs = { + "path": attr.string(mandatory=True) + }, + ) + \"\"\"A repository rule. + + Args: + name: A unique name for this rule. + path: The path of the external dependency. + \"\"\" + """) + + expected = textwrap.dedent("""\ + rule { + name: "repo_rule" + documentation: "A repository rule." + attribute { + name: "name" + type: UNKNOWN + mandatory: true + documentation: "A unique name for this rule." + } + attribute { + name: "path" + type: STRING + mandatory: true + documentation: "The path of the external dependency." + default: "\'\'" + } + type: REPOSITORY_RULE + } + """) + + self.check_protos(src, expected) + if __name__ == '__main__': unittest.main() diff --git a/skydoc/sass/main.scss b/skydoc/sass/main.scss index 8cf8de4..8d43f53 100644 --- a/skydoc/sass/main.scss +++ b/skydoc/sass/main.scss @@ -136,7 +136,7 @@ table { table.params-table { width: 100%; - col.col-param{ + col.col-param { width: 25%; } @@ -145,6 +145,24 @@ table.params-table { } } +table.overview-table { + width: 100%; + + col.col-name { + width: 25%; + } + + col.col-description { + width: 75%; + } + + td { + p { + margin: 0; + } + } +} + hr { margin-top: 80px; margin-bottom: 80px; diff --git a/skydoc/templates/BUILD b/skydoc/templates/BUILD index cac03e2..dad67e5 100644 --- a/skydoc/templates/BUILD +++ b/skydoc/templates/BUILD @@ -5,9 +5,14 @@ filegroup( srcs = [ "attributes.jinja", "html.jinja", + "html_footer.jinja", + "html_header.jinja", + "html_overview.jinja", "markdown.jinja", + "markdown_overview.jinja", "nav.jinja", "outputs.jinja", + "overview.jinja", "toc.jinja", ], ) diff --git a/skydoc/templates/html.jinja b/skydoc/templates/html.jinja index 01de607..15d9fa9 100644 --- a/skydoc/templates/html.jinja +++ b/skydoc/templates/html.jinja @@ -13,51 +13,16 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. #} - - - - - - - +% include "html_header.jinja" - {{ ruleset.title }} - - - - - - - - -
-
-
- {{ ruleset.title }} -
-
-
- Bazel - -
- -
-

{{ ruleset.title }}

% include "toc.jinja" % if ruleset.description:
-

Overview

+

Overview

{{ ruleset.description|markdown }} % endif -% for rule in ruleset.rules +% for rule in ruleset.definitions

{{ rule.name }}

@@ -84,18 +49,5 @@ Documentation generated by Skydoc % endif % endfor -
- -
-
- - +% include "html_footer.jinja" diff --git a/skydoc/templates/html_footer.jinja b/skydoc/templates/html_footer.jinja new file mode 100644 index 0000000..8336230 --- /dev/null +++ b/skydoc/templates/html_footer.jinja @@ -0,0 +1,31 @@ +{# +Copyright 2016 The Bazel Authors. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +#} + + + + + + + + diff --git a/skydoc/templates/html_header.jinja b/skydoc/templates/html_header.jinja new file mode 100644 index 0000000..1d9d5fe --- /dev/null +++ b/skydoc/templates/html_header.jinja @@ -0,0 +1,52 @@ +{# +Copyright 2016 The Bazel Authors. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +#} + + + + + + + + + {{ title }} + + + + + + + + +
+
+
+ {{ title }} +
+
+
+ Bazel + +
+ +
+
diff --git a/skydoc/templates/html_overview.jinja b/skydoc/templates/html_overview.jinja new file mode 100644 index 0000000..7abdcfd --- /dev/null +++ b/skydoc/templates/html_overview.jinja @@ -0,0 +1,22 @@ +{# +Copyright 2016 The Bazel Authors. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +#} +% include "html_header.jinja" + +

Overview

+ +% include "overview.jinja" + +% include "html_footer.jinja" diff --git a/skydoc/templates/markdown.jinja b/skydoc/templates/markdown.jinja index c912da8..5545bc0 100644 --- a/skydoc/templates/markdown.jinja +++ b/skydoc/templates/markdown.jinja @@ -30,7 +30,7 @@ Documentation generated by Skydoc {# I want a blank line here #} % endif -% for rule in ruleset.rules: +% for rule in ruleset.definitions: ## {{ rule.name }} diff --git a/skydoc/templates/markdown_overview.jinja b/skydoc/templates/markdown_overview.jinja new file mode 100644 index 0000000..f810a7e --- /dev/null +++ b/skydoc/templates/markdown_overview.jinja @@ -0,0 +1,18 @@ +{# +Copyright 2016 The Bazel Authors. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +#} +# Overview + +% include "overview.jinja" diff --git a/skydoc/templates/nav.jinja b/skydoc/templates/nav.jinja index eae6b28..c4a3234 100644 --- a/skydoc/templates/nav.jinja +++ b/skydoc/templates/nav.jinja @@ -14,14 +14,21 @@ See the License for the specific language governing permissions and limitations under the License. #} % for ruleset in rulesets: +% if overview: +
  • Overview
  • +% endif
  • - {{ ruleset.name }} + {{ ruleset.title }}
  • diff --git a/skydoc/templates/overview.jinja b/skydoc/templates/overview.jinja new file mode 100644 index 0000000..1386c7a --- /dev/null +++ b/skydoc/templates/overview.jinja @@ -0,0 +1,100 @@ +{# +Copyright 2016 The Bazel Authors. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +#} + + +% for ruleset in rulesets: +

    {{ ruleset.title }}

    + +% if ruleset.rules[0] is defined: +

    Rules

    + + + + + + +% for rule in ruleset.rules: + + + + +% endfor + +
    + + {{ rule.name }} + + + {{ rule.short_documentation | markdown }} +
    +% endif + +% if ruleset.macros[0] is defined: +

    Macros

    + + + + + + +% for rule in ruleset.macros: + + + + +% endfor + +
    + + {{ rule.name }} + + + {{ rule.short_documentation | markdown }} +
    +% endif + +% if ruleset.repository_rules[0] is defined: +

    Repository Rules

    + + + + + + +% for rule in ruleset.repository_rules: + + + + +% endfor + +
    + + {{ rule.name }} + + + {{ rule.short_documentation | markdown }} +
    +% endif + +% endfor diff --git a/skylark/BUILD b/skylark/BUILD index 5834a7e..6a60f68 100644 --- a/skylark/BUILD +++ b/skylark/BUILD @@ -6,4 +6,5 @@ skylark_doc( name = "skylark-docs", srcs = ["skylark.bzl"], strip_prefix = "skylark", + overview = False, ) diff --git a/skylark/skylark.bzl b/skylark/skylark.bzl index df29363..6c9d953 100644 --- a/skylark/skylark.bzl +++ b/skylark/skylark.bzl @@ -54,6 +54,12 @@ def _skylark_doc_impl(ctx): ] if ctx.attr.strip_prefix: flags += ["--strip_prefix=%s" % ctx.attr.strip_prefix] + if ctx.attr.overview: + flags += ["--overview"] + if ctx.attr.overview_filename: + flags += ["--overview_filename=%s" % ctx.attr.overview_filename] + if ctx.attr.link_ext: + flags += ["--link_ext=%s" % ctx.attr.link_ext] skydoc = _skydoc(ctx) ctx.action( inputs = list(inputs) + [skydoc], @@ -154,6 +160,9 @@ Example: _skylark_doc_attrs = { "format": attr.string(default = "markdown"), "strip_prefix": attr.string(), + "overview": attr.bool(default = True), + "overview_filename": attr.string(), + "link_ext": attr.string(), "skydoc": attr.label( default = Label("//skydoc"), cfg = HOST_CFG, @@ -192,6 +201,12 @@ Args: The directory prefix to strip must be common to all input files. Otherwise, skydoc will raise an error. + overview: If set to `True`, then generate an overview page. + overview_filename: The file name to use for the overview page. By default, + the page is named `index.md` or `index.html` for Markdown and HTML output + respectively. + link_ext: The file extension used for links in the generated documentation. + By default, skydoc uses `.html`. Outputs: skylark_doc_zip: A zip file containing the generated documentation.