From 7691fb14c1c0d80bcdd3cde6fa791884f44bc8d3 Mon Sep 17 00:00:00 2001 From: Sven Slootweg Date: Wed, 9 Jan 2013 21:35:31 +0100 Subject: [PATCH 1/9] Allow nested argument specifications --- zpy2html.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/zpy2html.py b/zpy2html.py index d0a8097..7968f34 100644 --- a/zpy2html.py +++ b/zpy2html.py @@ -87,6 +87,16 @@ template = """ font-weight: normal; margin-left: 8px; } + + dd > .children + { + font-size: 95%%; + } + + dd > .children > dl > dd + { + margin-left: 13px; + } .exclamation { @@ -254,7 +264,7 @@ class Argument(TreeLevel): self.data = data def render(self): - return '
%s
%s
' % (self.argname, self.process_inline_markup(self.data)) + return '
%s
%s%s
' % (self.argname, self.process_inline_markup(self.data), self.render_children()) class Header(TreeLevel): def __init__(self, indentation, data, depth): From 95bb26f882a4c0f997d638847783d98f0a346566 Mon Sep 17 00:00:00 2001 From: Sven Slootweg Date: Wed, 9 Jan 2013 22:08:38 +0100 Subject: [PATCH 2/9] Split up the converter into a module and a conversion script --- template.html | 161 +++++++++++++++++ zippydoc/__init__.py | 2 + zippydoc/block_markup.py | 141 +++++++++++++++ zippydoc/parser.py | 86 +++++++++ zpy2html.py | 379 +-------------------------------------- 5 files changed, 393 insertions(+), 376 deletions(-) create mode 100644 template.html create mode 100644 zippydoc/__init__.py create mode 100644 zippydoc/block_markup.py create mode 100644 zippydoc/parser.py diff --git a/template.html b/template.html new file mode 100644 index 0000000..d8ea410 --- /dev/null +++ b/template.html @@ -0,0 +1,161 @@ + + + + + + + {CONTENT} + + diff --git a/zippydoc/__init__.py b/zippydoc/__init__.py new file mode 100644 index 0000000..e2e7e54 --- /dev/null +++ b/zippydoc/__init__.py @@ -0,0 +1,2 @@ +from block_markup import * +from parser import * diff --git a/zippydoc/block_markup.py b/zippydoc/block_markup.py new file mode 100644 index 0000000..b7f07c2 --- /dev/null +++ b/zippydoc/block_markup.py @@ -0,0 +1,141 @@ +import re + +class TreeLevel: + def __init__(self, indentation, data): + self.elements = [] + self.indentation = indentation + self.data = data + + def add(self, element): + self.elements.append(element) + + def output(self): + return self.render() + + def render_children(self): + child_output = "" + + for child in self.elements: + child_output += child.output() + + return '
%s
' % child_output + + def process_inline_markup(self, text): + text = re.sub("`([^`]+)`", '\\1', text) # Fixed-width + text = re.sub("\*\*([^*]+)\*\*", "\\1", text) # Emphasized + text = re.sub("__([^_]+)__", "\\1", text) # Strong + text = re.sub("{>([^}]+)}\(([^)]+)\)", '\\2', text) # Hyperlink with text + text = re.sub("{>([^}]+)}", '\\1', text) # Hyperlink + text = re.sub("{([^}]+:[^}]+)}\(([^)]+)\)", '\\2', text) # External hyperlink with text + text = re.sub("{([^}]+:[^}]+)}", '\\1', text) # External hyperlink + text = re.sub("{<([^}]+)}\(([^)]+)\)", '\\2', text) # Forced external hyperlink with text + text = re.sub("{<([^}]+)}", '\\1', text) # Forced external hyperlink + + return text + + def clear_markup(self, text): + text = re.sub("`([^`]+)`", '\\1', text) # Fixed-width + text = re.sub("\*\*([^*]+)\*\*", "\\1", text) # Emphasized + text = re.sub("__([^_]+)__", "\\1", text) # Strong + text = re.sub("{>([^}]+)}\(([^)]+)\)", '\\2', text) # Hyperlink with text + text = re.sub("{>([^}]+)}", '\\1', text) # Hyperlink + text = re.sub("{([^}]+:[^}]+)}\(([^)]+)\)", '\\2', text) # External hyperlink with text + text = re.sub("{([^}]+:[^}]+)}", '\\1', text) # External hyperlink + text = re.sub("{<([^}]+)}\(([^)]+)\)", '\\2', text) # Forced external hyperlink with text + text = re.sub("{<([^}]+)}", '\\1', text) # Forced external hyperlink + + return text + + def fix_preformatted(self, text): + return text.replace("<", "<").replace(">", ">") + + def render(self): + return self.render_children() + +class Header(TreeLevel): + def __init__(self, indentation, data, depth): + self.elements = [] + self.indentation = indentation + self.data = data + self.depth = depth + + def render(self): + if self.depth <= 7: + title_type = "h%d" % self.depth + else: + title_type = "h7" + + return "<%s>%s" % (title_type, self.data, title_type) + +class Text(TreeLevel): + def render(self): + return '
%s
' % self.process_inline_markup(self.data) + +class Exclamation(TreeLevel): + def render(self): + return '
Important: %s
' % self.process_inline_markup(self.data) + +class Definition(TreeLevel): + def get_anchor(self): + first = self.clear_markup(self.data.splitlines()[0]) + anchor = first.replace("...", "") + anchor = anchor.replace(".", "_") + anchor = re.sub("[^a-zA-Z0-9_]", "", anchor) + return anchor + + def get_description(self): + for element in self.elements: + if element.__class__.__name__ == "Text": + data = self.process_inline_markup(element.data) + + if len(data) > 80: + matches = re.match("^(.{0,80})\W", data) + return matches.group(1) + "..." + else: + return data + + return "" + + def render(self): + return '' % (self.get_anchor(), self.process_inline_markup(self.data.replace("\n", "
")), self.render_children()) + +class Argument(TreeLevel): + def __init__(self, indentation, data, argname): + self.elements = [] + self.indentation = indentation + self.data = data + self.argname = argname + + def render(self): + return '
%s
%s%s
' % (self.argname, self.process_inline_markup(self.data), self.render_children()) + +class Example(TreeLevel): + def render(self): + return '
Example: %s %s
' % (self.data, self.render_children()) + +class Code(TreeLevel): + def render(self): + return 'Code:
%s
' % self.fix_preformatted(self.data) + +class Output(TreeLevel): + def render(self): + return 'Output:
%s
' % self.fix_preformatted(self.data) + +class Index(TreeLevel): + def render(self): + rendered = "" + + for item in self.data.toc_items: + forms = item.data.splitlines() + first = self.clear_markup(forms[0]) + + if len(forms) > 1: + rest = '(also: ' + ', '.join(self.clear_markup(form) for form in forms[1:]) + ")" + else: + rest = "" + + anchor = item.get_anchor() + description = item.get_description() + rendered += '
  • %s %s %s
  • ' % (anchor, first, description, rest) + + return '

    Table of contents

      %s
    ' % rendered diff --git a/zippydoc/parser.py b/zippydoc/parser.py new file mode 100644 index 0000000..57cdbc0 --- /dev/null +++ b/zippydoc/parser.py @@ -0,0 +1,86 @@ +from block_markup import * + +class Parser(): + def __init__(self, template): + self.template = template + + def render(self, text): + paragraphs = re.split("\s*\n\s*\n", text) + self.toc_items = [] + current_level = 0 + current_paragraph = 0 + current_elements = {0: TreeLevel(0, "root")} + + for paragraph in paragraphs: + if paragraph.strip() == "": + continue + + current_paragraph += 1 + indentation = len(paragraph) - len(paragraph.lstrip("\t")) + 1 + + if indentation > current_level + 1: + raise Exception("Invalid indentation found in paragraph %d" % current_paragraph) + + element_type = TreeLevel + start = indentation - 1 + + lines = [line[start:] for line in paragraph.splitlines()] + + if lines[0].startswith("#"): + element_type = Header + depth = len(lines[0]) - len(lines[0].lstrip("#")) + lines[0] = lines[0].lstrip("# ") + data = " ".join(lines) + elif lines[0].startswith("^"): + element_type = Definition + lines[0] = lines[0].lstrip("^ ") + data = "\n".join(lines) + elif lines[0].startswith("@"): + element_type = Example + lines[0] = lines[0].lstrip("@ ") + data = " ".join(lines) + elif lines[0].startswith("$$") and current_elements[current_level].__class__.__name__ == "Code": + current_elements[current_level].data += "\n\n" + "\n".join(lines).lstrip("$ ") + continue + elif lines[0].startswith("$"): + element_type = Code + lines[0] = lines[0].lstrip("$ ") + data = "\n".join(lines) + elif lines[0].startswith(">>") and current_elements[current_level].__class__.__name__ == "Output": + current_elements[current_level].data += "\n\n" + "\n".join(lines).lstrip("> ") + continue + elif lines[0].startswith(">"): + element_type = Output + lines[0] = lines[0].lstrip("> ") + data = "\n".join(lines) + elif lines[0].startswith("!"): + element_type = Exclamation + lines[0] = lines[0].lstrip("! ") + data = " ".join(lines) + elif re.match(".*::\s*$", lines[0]): + element_type = Argument + argname = lines[0][:-2] + data = " ".join(line.lstrip() for line in lines[1:]) + elif lines[0].strip() == "{TOC}": + element_type = Index + data = self + else: + element_type = Text + data = " ".join(lines) + + if element_type.__name__ == "Header": + element = Header(indentation, data, depth) + elif element_type.__name__ == "Argument": + element = Argument(indentation, data, argname) + else: + element = element_type(indentation, data) + + if element_type.__name__ == "Definition": + self.toc_items.append(element) + + current_elements[indentation - 1].add(element) + + current_level = indentation + current_elements[current_level] = element + + return self.template.replace("{CONTENT}", current_elements[0].output()) diff --git a/zpy2html.py b/zpy2html.py index 7968f34..f391d23 100644 --- a/zpy2html.py +++ b/zpy2html.py @@ -1,4 +1,5 @@ import os, argparse, sys, re +import zippydoc parser = argparse.ArgumentParser(description='Converts ZippyDoc source files to HTML.') @@ -10,301 +11,7 @@ options = vars(args) files = options["files"] -template = """ - - - - - - - %s - - -""" - -class TreeLevel: - def __init__(self, indentation, data): - self.elements = [] - self.indentation = indentation - self.data = data - - def add(self, element): - self.elements.append(element) - - def output(self): - return self.render() - - def render_children(self): - child_output = "" - - for child in self.elements: - child_output += child.output() - - return '
    %s
    ' % child_output - - def process_inline_markup(self, text): - text = re.sub("`([^`]+)`", '\\1', text) # Emphasized - text = re.sub("\*\*([^*]+)\*\*", "\\1", text) # Emphasized - text = re.sub("__([^_]+)__", "\\1", text) # Strong - text = re.sub("{>([^}]+)}\(([^)]+)\)", '\\2', text) # Hyperlink with text - text = re.sub("{>([^}]+)}", '\\1', text) # Hyperlink - text = re.sub("{([^}]+:[^}]+)}\(([^)]+)\)", '\\2', text) # External hyperlink with text - text = re.sub("{([^}]+:[^}]+)}", '\\1', text) # External hyperlink - text = re.sub("{<([^}]+)}\(([^)]+)\)", '\\2', text) # Forced external hyperlink with text - text = re.sub("{<([^}]+)}", '\\1', text) # Forced external hyperlink - - return text - - def fix_preformatted(self, text): - return text.replace("<", "<").replace(">", ">") - - def clear_markup(self, text): - return re.sub("\*\*([^*]+)\*\*", "\\1", text) - - def render(self): - return self.render_children() - -class Example(TreeLevel): - def render(self): - return '
    Example: %s %s
    ' % (self.data, self.render_children()) - -class Code(TreeLevel): - def render(self): - return 'Code:
    %s
    ' % self.fix_preformatted(self.data) - -class Output(TreeLevel): - def render(self): - return 'Output:
    %s
    ' % self.fix_preformatted(self.data) - -class Definition(TreeLevel): - def get_anchor(self): - first = self.clear_markup(self.data.splitlines()[0]) - anchor = first.replace("...", "") - anchor = anchor.replace(".", "_") - anchor = re.sub("[^a-zA-Z0-9_]", "", anchor) - return anchor - - def get_description(self): - for element in self.elements: - if element.__class__.__name__ == "Text": - data = self.process_inline_markup(element.data) - - if len(data) > 80: - matches = re.match("^(.{0,80})\W", data) - return matches.group(1) + "..." - else: - return data - - return "" - - def render(self): - return '' % (self.get_anchor(), self.process_inline_markup(self.data.replace("\n", "
    ")), self.render_children()) - -class Exclamation(TreeLevel): - def render(self): - return '
    Important: %s
    ' % self.process_inline_markup(self.data) - -class Argument(TreeLevel): - def __init__(self, indentation, data, argname): - self.elements = [] - self.indentation = indentation - self.argname = argname - self.data = data - - def render(self): - return '
    %s
    %s%s
    ' % (self.argname, self.process_inline_markup(self.data), self.render_children()) - -class Header(TreeLevel): - def __init__(self, indentation, data, depth): - self.elements = [] - self.indentation = indentation - self.depth = depth - self.data = data - - def render(self): - if self.depth <= 7: - title_type = "h%d" % self.depth - else: - title_type = "h7" - - return "<%s>%s" % (title_type, self.data, title_type) - -class Text(TreeLevel): - def render(self): - return '
    %s
    ' % self.process_inline_markup(self.data) - -class Index(TreeLevel): - def render(self): - global toc_items - - rendered = "" - - for item in toc_items: - forms = item.data.splitlines() - first = self.clear_markup(forms[0]) - - if len(forms) > 1: - rest = '(also: ' + ', '.join(self.clear_markup(form) for form in forms[1:]) + ")" - else: - rest = "" - - anchor = item.get_anchor() - description = item.get_description() - rendered += '
  • %s %s %s
  • ' % (anchor, first, description, rest) - - return '

    Table of contents

      %s
    ' % rendered +docparser = zippydoc.Parser(open("template.html").read()) for zpy in files: destination = os.path.splitext(zpy)[0] + ".html" @@ -313,87 +20,7 @@ for zpy in files: data = f.read() f.close() - paragraphs = re.split("\s*\n\s*\n", data) - toc_items = [] - current_level = 0 - current_paragraph = 0 - current_elements = {0: TreeLevel(0, "root")} - - for paragraph in paragraphs: - if paragraph.strip() == "": - continue - - current_paragraph += 1 - indentation = len(paragraph) - len(paragraph.lstrip("\t")) + 1 - - if indentation > current_level + 1: - raise Exception("Invalid indentation found in paragraph %d" % current_paragraph) - - element_type = TreeLevel - start = indentation - 1 - - lines = [line[start:] for line in paragraph.splitlines()] - - if lines[0].startswith("#"): - element_type = Header - depth = len(lines[0]) - len(lines[0].lstrip("#")) - lines[0] = lines[0].lstrip("# ") - data = " ".join(lines) - elif lines[0].startswith("^"): - element_type = Definition - lines[0] = lines[0].lstrip("^ ") - data = "\n".join(lines) - elif lines[0].startswith("@"): - element_type = Example - lines[0] = lines[0].lstrip("@ ") - data = " ".join(lines) - elif lines[0].startswith("$$") and current_elements[current_level].__class__.__name__ == "Code": - current_elements[current_level].data += "\n\n" + "\n".join(lines).lstrip("$ ") - continue - elif lines[0].startswith("$"): - element_type = Code - lines[0] = lines[0].lstrip("$ ") - data = "\n".join(lines) - elif lines[0].startswith(">>") and current_elements[current_level].__class__.__name__ == "Output": - current_elements[current_level].data += "\n\n" + "\n".join(lines).lstrip("> ") - continue - elif lines[0].startswith(">"): - element_type = Output - lines[0] = lines[0].lstrip("> ") - data = "\n".join(lines) - elif lines[0].startswith("!"): - element_type = Exclamation - lines[0] = lines[0].lstrip("! ") - data = " ".join(lines) - elif re.match(".*::\s*$", lines[0]): - element_type = Argument - argname = lines[0][:-2] - data = " ".join(line.lstrip() for line in lines[1:]) - elif lines[0].strip() == "{TOC}": - element_type = Index - data = "" - else: - element_type = Text - data = " ".join(lines) - - #print "Found element of type %s at indentation %d with data %s" % (element_type.__name__, indentation, data[:80]) - - if element_type.__name__ == "Header": - element = Header(indentation, data, depth) - elif element_type.__name__ == "Argument": - element = Argument(indentation, data, argname) - else: - element = element_type(indentation, data) - - if element_type.__name__ == "Definition": - toc_items.append(element) - - current_elements[indentation - 1].add(element) - - current_level = indentation - current_elements[current_level] = element - - rendered = template % (current_elements[0].output()) + rendered = docparser.render(data) f = open(destination, "w") f.write(rendered) From 6bc3054acada1eda04528acbff986bb7ba770c39 Mon Sep 17 00:00:00 2001 From: Sven Slootweg Date: Thu, 10 Jan 2013 01:38:38 +0100 Subject: [PATCH 3/9] Full rewrite to use transformation rulesets --- zippydoc/__init__.py | 4 +- zippydoc/block_markup.py | 128 ++++++++--------------------- zippydoc/document.py | 85 +++++++++++++++++++ zippydoc/parser.py | 86 ------------------- zippydoc/transformation_ruleset.py | 45 ++++++++++ zippydoc/value.py | 29 +++++++ zpy2html.py | 90 +++++++++++++++++++- 7 files changed, 285 insertions(+), 182 deletions(-) create mode 100644 zippydoc/document.py delete mode 100644 zippydoc/parser.py create mode 100644 zippydoc/transformation_ruleset.py create mode 100644 zippydoc/value.py diff --git a/zippydoc/__init__.py b/zippydoc/__init__.py index e2e7e54..d328b10 100644 --- a/zippydoc/__init__.py +++ b/zippydoc/__init__.py @@ -1,2 +1,4 @@ from block_markup import * -from parser import * +from document import * +from transformation_ruleset import * +from value import * diff --git a/zippydoc/block_markup.py b/zippydoc/block_markup.py index b7f07c2..3d1187d 100644 --- a/zippydoc/block_markup.py +++ b/zippydoc/block_markup.py @@ -1,4 +1,5 @@ import re +from value import Value class TreeLevel: def __init__(self, indentation, data): @@ -8,49 +9,17 @@ class TreeLevel: def add(self, element): self.elements.append(element) - - def output(self): - return self.render() - - def render_children(self): + + def transform(self, ruleset): + return self.transform_children(ruleset) + + def transform_children(self, ruleset): child_output = "" for child in self.elements: - child_output += child.output() + child_output += child.transform(ruleset) - return '
    %s
    ' % child_output - - def process_inline_markup(self, text): - text = re.sub("`([^`]+)`", '\\1', text) # Fixed-width - text = re.sub("\*\*([^*]+)\*\*", "\\1", text) # Emphasized - text = re.sub("__([^_]+)__", "\\1", text) # Strong - text = re.sub("{>([^}]+)}\(([^)]+)\)", '\\2', text) # Hyperlink with text - text = re.sub("{>([^}]+)}", '\\1', text) # Hyperlink - text = re.sub("{([^}]+:[^}]+)}\(([^)]+)\)", '\\2', text) # External hyperlink with text - text = re.sub("{([^}]+:[^}]+)}", '\\1', text) # External hyperlink - text = re.sub("{<([^}]+)}\(([^)]+)\)", '\\2', text) # Forced external hyperlink with text - text = re.sub("{<([^}]+)}", '\\1', text) # Forced external hyperlink - - return text - - def clear_markup(self, text): - text = re.sub("`([^`]+)`", '\\1', text) # Fixed-width - text = re.sub("\*\*([^*]+)\*\*", "\\1", text) # Emphasized - text = re.sub("__([^_]+)__", "\\1", text) # Strong - text = re.sub("{>([^}]+)}\(([^)]+)\)", '\\2', text) # Hyperlink with text - text = re.sub("{>([^}]+)}", '\\1', text) # Hyperlink - text = re.sub("{([^}]+:[^}]+)}\(([^)]+)\)", '\\2', text) # External hyperlink with text - text = re.sub("{([^}]+:[^}]+)}", '\\1', text) # External hyperlink - text = re.sub("{<([^}]+)}\(([^)]+)\)", '\\2', text) # Forced external hyperlink with text - text = re.sub("{<([^}]+)}", '\\1', text) # Forced external hyperlink - - return text - - def fix_preformatted(self, text): - return text.replace("<", "<").replace(">", ">") - - def render(self): - return self.render_children() + return ruleset.transform_children(child_output) class Header(TreeLevel): def __init__(self, indentation, data, depth): @@ -59,83 +28,58 @@ class Header(TreeLevel): self.data = data self.depth = depth - def render(self): - if self.depth <= 7: - title_type = "h%d" % self.depth - else: - title_type = "h7" - - return "<%s>%s" % (title_type, self.data, title_type) + def transform(self, ruleset): + return ruleset.transform_header(self.depth, Value(self.data)) class Text(TreeLevel): - def render(self): - return '
    %s
    ' % self.process_inline_markup(self.data) + def transform(self, ruleset): + return ruleset.transform_text(Value(self.data)) class Exclamation(TreeLevel): - def render(self): - return '
    Important: %s
    ' % self.process_inline_markup(self.data) + def transform(self, ruleset): + return ruleset.transform_exclamation(Value(self.data), self.transform_children(ruleset)) class Definition(TreeLevel): - def get_anchor(self): - first = self.clear_markup(self.data.splitlines()[0]) - anchor = first.replace("...", "") - anchor = anchor.replace(".", "_") - anchor = re.sub("[^a-zA-Z0-9_]", "", anchor) - return anchor + def __init__(self, indentation, forms): + self.elements = [] + self.indentation = indentation + self.forms = [form.lstrip() for form in forms] + + def transform(self, ruleset): + return ruleset.transform_definition([Value(form) for form in self.forms], self.transform_children(ruleset)) + + def get_forms(self): + return [Value(form) for form in self.forms] def get_description(self): for element in self.elements: if element.__class__.__name__ == "Text": - data = self.process_inline_markup(element.data) - - if len(data) > 80: - matches = re.match("^(.{0,80})\W", data) - return matches.group(1) + "..." - else: - return data + return element.data return "" - def render(self): - return '' % (self.get_anchor(), self.process_inline_markup(self.data.replace("\n", "
    ")), self.render_children()) - class Argument(TreeLevel): def __init__(self, indentation, data, argname): self.elements = [] self.indentation = indentation self.data = data self.argname = argname - - def render(self): - return '
    %s
    %s%s
    ' % (self.argname, self.process_inline_markup(self.data), self.render_children()) + + def transform(self, ruleset): + return ruleset.transform_argument(Value(self.argname), Value(self.data), self.transform_children(ruleset)) class Example(TreeLevel): - def render(self): - return '
    Example: %s %s
    ' % (self.data, self.render_children()) + def transform(self, ruleset): + return ruleset.transform_example(Value(self.data), self.transform_children(ruleset)) class Code(TreeLevel): - def render(self): - return 'Code:
    %s
    ' % self.fix_preformatted(self.data) + def transform(self, ruleset): + return ruleset.transform_code(self.data) class Output(TreeLevel): - def render(self): - return 'Output:
    %s
    ' % self.fix_preformatted(self.data) + def transform(self, ruleset): + return ruleset.transform_output(Value(self.data)) class Index(TreeLevel): - def render(self): - rendered = "" - - for item in self.data.toc_items: - forms = item.data.splitlines() - first = self.clear_markup(forms[0]) - - if len(forms) > 1: - rest = '(also: ' + ', '.join(self.clear_markup(form) for form in forms[1:]) + ")" - else: - rest = "" - - anchor = item.get_anchor() - description = item.get_description() - rendered += '
  • %s %s %s
  • ' % (anchor, first, description, rest) - - return '

    Table of contents

      %s
    ' % rendered + def transform(self, ruleset): + return ruleset.transform_toc([(definition, Value(definition.get_description())) for definition in self.data.get_definitions()]) diff --git a/zippydoc/document.py b/zippydoc/document.py new file mode 100644 index 0000000..bbfd741 --- /dev/null +++ b/zippydoc/document.py @@ -0,0 +1,85 @@ +import re +import block_markup + +class Document(): + def __init__(self, data): + self.data = data + self._parse() + + def _parse(self): + paragraphs = re.split("\s*\n\s*\n", self.data) + + self.paragraphs = paragraphs + self.definitions = [] + + current_level = 0 + current_paragraph = 0 + self.current_elements = {0: block_markup.TreeLevel(0, "root")} + + for paragraph in paragraphs: + if paragraph.strip() == "": + continue + + current_paragraph += 1 + indentation = len(paragraph) - len(paragraph.lstrip("\t")) + 1 + + if indentation > current_level + 1: + raise Exception("Invalid indentation found in paragraph %d" % current_paragraph) + + start = indentation - 1 + lines = [line[start:] for line in paragraph.splitlines()] + + if lines[0].startswith("#"): + # Header + depth = len(lines[0]) - len(lines[0].lstrip("#")) + lines[0] = lines[0].lstrip("# ") + element = block_markup.Header(indentation, " ".join(lines), depth) + elif lines[0].startswith("^"): + # Definition + lines[0] = lines[0].lstrip("^ ") + element = block_markup.Definition(indentation, lines) + self.definitions.append(element) + elif lines[0].startswith("@"): + # Example + lines[0] = lines[0].lstrip("@ ") + element = block_markup.Example(indentation, " ".join(lines)) + elif lines[0].startswith("$$") and self.current_elements[current_level].__class__.__name__ == "Code": + # Code continuation + self.current_elements[current_level].data += "\n\n" + "\n".join(lines).lstrip("$ ") + continue + elif lines[0].startswith("$"): + # Code block start + lines[0] = lines[0].lstrip("$ ") + element = block_markup.Code(indentation, "\n".join(lines)) + elif lines[0].startswith(">>") and self.current_elements[current_level].__class__.__name__ == "Output": + # Output continuation + self.current_elements[current_level].data += "\n\n" + "\n".join(lines).lstrip("> ") + continue + elif lines[0].startswith(">"): + # Output block start + lines[0] = lines[0].lstrip("> ") + element = block_markup.Output(indentation, "\n".join(lines)) + elif lines[0].startswith("!"): + # Exclamation + lines[0] = lines[0].lstrip("! ") + element = block_markup.Exclamation(indentation, " ".join(lines)) + elif re.match(".*::\s*$", lines[0]): + # Argument definition + argname = re.match("(.*)::\s*$", lines[0]).group(1) + element = block_markup.Argument(indentation, " ".join(line.lstrip() for line in lines[1:]), argname) + elif lines[0].strip() == "{TOC}": + # Table of contents + element = block_markup.Index(indentation, self) + else: + # Text + element = block_markup.Text(indentation, " ".join(lines)) + + self.current_elements[indentation - 1].add(element) + current_level = indentation + self.current_elements[current_level] = element + + def transform(self, ruleset): + return self.current_elements[0].transform(ruleset) + + def get_definitions(self): + return self.definitions diff --git a/zippydoc/parser.py b/zippydoc/parser.py deleted file mode 100644 index 57cdbc0..0000000 --- a/zippydoc/parser.py +++ /dev/null @@ -1,86 +0,0 @@ -from block_markup import * - -class Parser(): - def __init__(self, template): - self.template = template - - def render(self, text): - paragraphs = re.split("\s*\n\s*\n", text) - self.toc_items = [] - current_level = 0 - current_paragraph = 0 - current_elements = {0: TreeLevel(0, "root")} - - for paragraph in paragraphs: - if paragraph.strip() == "": - continue - - current_paragraph += 1 - indentation = len(paragraph) - len(paragraph.lstrip("\t")) + 1 - - if indentation > current_level + 1: - raise Exception("Invalid indentation found in paragraph %d" % current_paragraph) - - element_type = TreeLevel - start = indentation - 1 - - lines = [line[start:] for line in paragraph.splitlines()] - - if lines[0].startswith("#"): - element_type = Header - depth = len(lines[0]) - len(lines[0].lstrip("#")) - lines[0] = lines[0].lstrip("# ") - data = " ".join(lines) - elif lines[0].startswith("^"): - element_type = Definition - lines[0] = lines[0].lstrip("^ ") - data = "\n".join(lines) - elif lines[0].startswith("@"): - element_type = Example - lines[0] = lines[0].lstrip("@ ") - data = " ".join(lines) - elif lines[0].startswith("$$") and current_elements[current_level].__class__.__name__ == "Code": - current_elements[current_level].data += "\n\n" + "\n".join(lines).lstrip("$ ") - continue - elif lines[0].startswith("$"): - element_type = Code - lines[0] = lines[0].lstrip("$ ") - data = "\n".join(lines) - elif lines[0].startswith(">>") and current_elements[current_level].__class__.__name__ == "Output": - current_elements[current_level].data += "\n\n" + "\n".join(lines).lstrip("> ") - continue - elif lines[0].startswith(">"): - element_type = Output - lines[0] = lines[0].lstrip("> ") - data = "\n".join(lines) - elif lines[0].startswith("!"): - element_type = Exclamation - lines[0] = lines[0].lstrip("! ") - data = " ".join(lines) - elif re.match(".*::\s*$", lines[0]): - element_type = Argument - argname = lines[0][:-2] - data = " ".join(line.lstrip() for line in lines[1:]) - elif lines[0].strip() == "{TOC}": - element_type = Index - data = self - else: - element_type = Text - data = " ".join(lines) - - if element_type.__name__ == "Header": - element = Header(indentation, data, depth) - elif element_type.__name__ == "Argument": - element = Argument(indentation, data, argname) - else: - element = element_type(indentation, data) - - if element_type.__name__ == "Definition": - self.toc_items.append(element) - - current_elements[indentation - 1].add(element) - - current_level = indentation - current_elements[current_level] = element - - return self.template.replace("{CONTENT}", current_elements[0].output()) diff --git a/zippydoc/transformation_ruleset.py b/zippydoc/transformation_ruleset.py new file mode 100644 index 0000000..d1b1c37 --- /dev/null +++ b/zippydoc/transformation_ruleset.py @@ -0,0 +1,45 @@ +class TransformationRuleset(): + def transform_children(self, text): + pass + + def transform_header(self, depth, text): + pass + + def transform_definition(self, forms, children): + pass + + def transform_argument(self, name, description, children): + pass + + def transform_example(self, title, children): + pass + + def transform_code(self, text): + pass + + def transform_output(self, text): + pass + + def transform_exclamation(self, text, children): + pass + + def transform_text(self, text): + pass + + def transform_reference(self, target, description): + pass + + def transform_external_reference(self, target, description): + pass + + def transform_fixed_width(self, text): + pass + + def transform_emphasis(self, text): + pass + + def transform_strong(self, text): + pass + + def transform_toc(self, items): + pass diff --git a/zippydoc/value.py b/zippydoc/value.py new file mode 100644 index 0000000..f63cd27 --- /dev/null +++ b/zippydoc/value.py @@ -0,0 +1,29 @@ +import re + +class Value(str): + def transform(self, ruleset): + text = self + text = re.sub("`([^`]+)`", lambda x: ruleset.transform_fixed_width(Value(x.group(1))), text) # Fixed-width + text = re.sub("\*\*([^*]+)\*\*", lambda x: ruleset.transform_emphasis(Value(x.group(1))), text) # Emphasized + text = re.sub("__([^_]+)__", lambda x: ruleset.transform_strong(Value(x.group(1))), text) # Strong + text = re.sub("{>([^}]+)}\(([^)]+)\)", lambda x: ruleset.transform_reference(Value(x.group(1)), Value(x.group(2))), text) # Hyperlink with text + text = re.sub("{>([^}]+)}", lambda x: ruleset.transform_reference(Value(x.group(1)), Value(x.group(1))), text) # Hyperlink + text = re.sub("{([^}]+:[^}]+)}\(([^)]+)\)", lambda x: ruleset.transform_external_reference(Value(x.group(1)), Value(x.group(2))), text) # External hyperlink with text + text = re.sub("{([^}]+:[^}]+)}", lambda x: ruleset.transform_external_reference(Value(x.group(1)), Value(x.group(1))), text) # External hyperlink + text = re.sub("{<([^}]+)}\(([^)]+)\)", lambda x: ruleset.transform_external_reference(Value(x.group(1)), Value(x.group(2))), text) # Forced external hyperlink with text + text = re.sub("{<([^}]+)}", lambda x: ruleset.transform_external_reference(Value(x.group(1)), Value(x.group(1))), text) # Forced external hyperlink + return text + + def clean(self): + text = self + text = re.sub("`([^`]+)`", '\\1', text) # Fixed-width + text = re.sub("\*\*([^*]+)\*\*", "\\1", text) # Emphasized + text = re.sub("__([^_]+)__", "\\1", text) # Strong + text = re.sub("{>([^}]+)}\(([^)]+)\)", '\\2', text) # Hyperlink with text + text = re.sub("{>([^}]+)}", '\\1', text) # Hyperlink + text = re.sub("{([^}]+:[^}]+)}\(([^)]+)\)", '\\2', text) # External hyperlink with text + text = re.sub("{([^}]+:[^}]+)}", '\\1', text) # External hyperlink + text = re.sub("{<([^}]+)}\(([^)]+)\)", '\\2', text) # Forced external hyperlink with text + text = re.sub("{<([^}]+)}", '\\1', text) # Forced external hyperlink + return text + diff --git a/zpy2html.py b/zpy2html.py index f391d23..7330883 100644 --- a/zpy2html.py +++ b/zpy2html.py @@ -9,9 +9,91 @@ parser.add_argument('files', metavar='FILE', type=str, nargs='+', args = parser.parse_args() options = vars(args) +class HtmlRuleset(zippydoc.TransformationRuleset): + def create_anchor(self, title): + anchor = title.clean().replace("...", "").replace(".", "_") + anchor = re.sub("[^a-zA-Z0-9_]", "", anchor) + return anchor + + def escape_html(self, text): + return text.replace("<", "<").replace(">", ">") + + def transform_children(self, text): + return '
    %s
    ' % text + + def transform_header(self, depth, text): + if depth <= 7: + title_type = "h%d" % depth + else: + title_type = "h7" + + return "<%s>%s" % (title_type, text.transform(self), title_type) + + def transform_definition(self, forms, children): + anchor = self.create_anchor(forms[0]) + formlist = "
    ".join([form.transform(self) for form in forms]) + return '' % (anchor, formlist, children) + + def transform_argument(self, name, description, children): + return "
    %s
    %s%s
    " % (name, description.transform(self), children) + + def transform_example(self, title, children): + return '
    Example: %s %s
    ' % (title.transform(self), children) + + def transform_code(self, text): + return 'Code:
    %s
    ' % self.escape_html(text) + + def transform_output(self, text): + return 'Output:
    %s
    ' % self.escape_html(text) + + def transform_exclamation(self, text, children): + return '
    Important: %s %s
    ' % (text.transform(self), children) + + def transform_text(self, text): + return '
    %s
    ' % text.transform(self) + + def transform_reference(self, target, description): + return '%s' % (target, description.transform(self)) + + def transform_external_reference(self, target, description): + return '%s' % (target, description.transform(self)) + + def transform_fixed_width(self, text): + return '%s' % text + + def transform_emphasis(self, text): + return "%s" % text.transform(self) + + def transform_strong(self, text): + return "%s" % text.transform(self) + + def transform_toc(self, items): + rendered = "" + + for item in items: + forms = item[0].get_forms() + anchor = self.create_anchor(forms[0]) + + if len(forms) > 1: + alternatives = '(also: %s)' % ", ".join(form.clean() for form in forms[1:]) + else: + alternatives = "" + + description = item[1] + + if len(description) > 80: + matches = re.match("^(.{0,80})\W", data) + description = matches.group(1) + "..." + + description = zippydoc.Value(description).transform(self) + + rendered += '
  • %s %s %s
  • ' % (anchor, forms[0].clean(), description, alternatives) + + return '

    Table of contents

      %s
    ' % rendered + files = options["files"] -docparser = zippydoc.Parser(open("template.html").read()) +template = open("template.html").read() for zpy in files: destination = os.path.splitext(zpy)[0] + ".html" @@ -20,10 +102,12 @@ for zpy in files: data = f.read() f.close() - rendered = docparser.render(data) + doc = zippydoc.Document(open(zpy, "r").read()) + + rendered = doc.transform(HtmlRuleset()) f = open(destination, "w") - f.write(rendered) + f.write(template.replace("{CONTENT}", rendered)) f.close() print "Rendered %s" % destination From b26e1abfc7f36975159b0b1fd15de4758d45564d Mon Sep 17 00:00:00 2001 From: Sven Slootweg Date: Thu, 10 Jan 2013 01:44:53 +0100 Subject: [PATCH 4/9] Fix classes --- zippydoc/block_markup.py | 2 +- zippydoc/document.py | 2 +- zippydoc/transformation_ruleset.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/zippydoc/block_markup.py b/zippydoc/block_markup.py index 3d1187d..cec6fd0 100644 --- a/zippydoc/block_markup.py +++ b/zippydoc/block_markup.py @@ -1,7 +1,7 @@ import re from value import Value -class TreeLevel: +class TreeLevel(object): def __init__(self, indentation, data): self.elements = [] self.indentation = indentation diff --git a/zippydoc/document.py b/zippydoc/document.py index bbfd741..dc1d5be 100644 --- a/zippydoc/document.py +++ b/zippydoc/document.py @@ -1,7 +1,7 @@ import re import block_markup -class Document(): +class Document(object): def __init__(self, data): self.data = data self._parse() diff --git a/zippydoc/transformation_ruleset.py b/zippydoc/transformation_ruleset.py index d1b1c37..13a5c2d 100644 --- a/zippydoc/transformation_ruleset.py +++ b/zippydoc/transformation_ruleset.py @@ -1,4 +1,4 @@ -class TransformationRuleset(): +class TransformationRuleset(object): def transform_children(self, text): pass From 96338fc1d5727ce1f3072b753a7e817563b5b9d9 Mon Sep 17 00:00:00 2001 From: Sven Slootweg Date: Thu, 10 Jan 2013 02:00:47 +0100 Subject: [PATCH 5/9] Fix bug in HtmlRuleset description parsing --- zpy2html.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zpy2html.py b/zpy2html.py index 7330883..8e8c292 100644 --- a/zpy2html.py +++ b/zpy2html.py @@ -82,7 +82,7 @@ class HtmlRuleset(zippydoc.TransformationRuleset): description = item[1] if len(description) > 80: - matches = re.match("^(.{0,80})\W", data) + matches = re.match("^(.{0,80})\W", description) description = matches.group(1) + "..." description = zippydoc.Value(description).transform(self) From b8bbefd7545e0f54228ea93896b4b81a59a2706d Mon Sep 17 00:00:00 2001 From: Sven Slootweg Date: Thu, 10 Jan 2013 02:04:03 +0100 Subject: [PATCH 6/9] Add documentation and homepage --- documentation.html | 285 ++++++++++++++++++++++++++++++++++++++ documentation.zpy | 333 +++++++++++++++++++++++++++++++++++++++++++++ example.html | 187 +++++++++++++++++++++++++ example.zpy | 51 +++++++ index.html | 177 ++++++++++++++++++++++++ index.zpy | 62 +++++++++ 6 files changed, 1095 insertions(+) create mode 100644 documentation.html create mode 100644 documentation.zpy create mode 100644 example.html create mode 100644 example.zpy create mode 100644 index.html create mode 100644 index.zpy diff --git a/documentation.html b/documentation.html new file mode 100644 index 0000000..3f4c271 --- /dev/null +++ b/documentation.html @@ -0,0 +1,285 @@ + + + + + + +

    ZippyDoc format documentation

    ZippyDoc is a compact, light-weight and code-oriented documentation markup language. It allows you to easily write documentation for your code or APIs, and batch-convert it to HTML.

    Table of contents

    • Definition block A definition block is prefixed with a caret, and contains something along the...
    • Argument block An argument block shows a particular argument or parameter, and its explanation....
    • Example block An example block shows an example of the function you are documenting, with code...
    • Code block The code block is used in an example to show example code. It is prefixed with a...
    • Output block The output block is used to display sample output in an example. Just like the...
    • Exclamation block The exclamation block allows you to mark a block of text as "important". In the...
    • Header block A header block is a generic header to indicate the start of a new section. It is...
    • Text block A text block is any block that is not prefixed by a special character. It is...
    • Emphasized text Emphasized text is typically displayed as italic. You can emphasize text by...
    • Strong text Strong text is typically displayed as bold. You can make text strong by...
    • Internal references (hyperlinks) Internal references are hyperlinks that point to other documents in the same...
    • External references (hyperlinks) External references are hyperlinks just like the internal references, but they...
    • Fixed-width text Fixed-width text can be useful to indicate code elements or other things that...
    • Table of contents To insert a table of contents that is automatically generated from all...

    Format overview

    ZippyDoc is a paragraph-oriented format, much like Markdown. Each paragraph represents a "block" of something, and no linebreaks are used anywhere - to start on a new line, you simply start out with a new paragraph. A block is indicated by a specific prefix. Tabs (not spaces!) are used to indent blocks and indicate children of previous blocks. A new "paragraph" is started by having two or more successive line-endings - this basically comes down to at least one empty line inbetween paragraphs.
    There is also some inline markup available, including emphasis, strong text, and hyperlinks to both other ZippyDoc documents and external locations.

    Blocks

    Several block types exist. Some of them have "continuation characters" that indicate the continuation of the previous block in a new paragraph, as opposed to starting a new block.
    Code block
    Important: This block cannot have child elements!
    The code block is used in an example to show example code. It is prefixed with a dollar sign ($), and all text following it will be show on the HTML page verbatim, without any further markup processing being done. It even allows you to display ZippyDoc formatting characters without having them interpreted, as is done on this page!
    Example: Using a code block
    Code:
    ^ my_function(**argument**, **another_argument**)
    +
    +	Some kind of text describing the function goes here.
    +
    +	argument::
    +		This is the first argument to this example function.
    +
    +	another_argument::
    +		This is the second argument to this example function.
    +		As you can see, it's possible to split the explanation over multiple lines as well.
    +
    +	@ Using this function
    +
    +		$ my_function(42, "The answer to everything")
    +
    +		> Some output goes here.
    It is also possible to have a code block spanning multiple paragraphs, without each paragraph being broken up into a separate code block (as would normally happen if you just used the dollar sign). To do this, you can use two dollar signs at the start of the block. Note that after these two dollar signs, whitespace (except for spaces) is not eaten, meaning you can use tabs to indent further blocks of your code!
    Example: Using a multi-paragraph code block
    Code:
    ^ my_function(**argument**, **another_argument**)
    +
    +	Some kind of text describing the function goes here.
    +
    +	argument::
    +		This is the first argument to this example function.
    +
    +	another_argument::
    +		This is the second argument to this example function.
    +		As you can see, it's possible to split the explanation over multiple lines as well.
    +
    +	@ Using this function
    +
    +		$ if some_variable == True:
    +
    +		$$	my_function(42, "The answer to everything")
    +
    +		> Some output goes here.

    Inline markup

    There are also various forms of inline markup that you can use in your documentation.

    Special tags

    Currently there is only one special tag. Special tags can be inserted anywhere in the document to insert a generated element.

    Full example

    You can view a full example here of a ZippyDoc source file and its result.
    + + diff --git a/documentation.zpy b/documentation.zpy new file mode 100644 index 0000000..cae8ac6 --- /dev/null +++ b/documentation.zpy @@ -0,0 +1,333 @@ +# ZippyDoc format documentation + +{ Some output goes here. + +^ Code block + + ! This block cannot have child elements! + + The code block is used in an example to show example code. It is prefixed with a dollar sign ($), and all text following it will be show on the HTML page verbatim, without + any further markup processing being done. It even allows you to display ZippyDoc formatting characters without having them interpreted, as is done on this page! + + @ Using a code block + + $ ^ my_function(**argument**, **another_argument**) + + $$ Some kind of text describing the function goes here. + + $$ argument:: + This is the first argument to this example function. + + $$ another_argument:: + This is the second argument to this example function. + As you can see, it's possible to split the explanation over multiple lines as well. + + $$ @ Using this function + + $$ $ my_function(42, "The answer to everything") + + $$ > Some output goes here. + + It is also possible to have a code block spanning multiple paragraphs, without each paragraph being broken up into a separate code block (as would normally happen if you + just used the dollar sign). To do this, you can use two dollar signs at the start of the block. Note that after these two dollar signs, whitespace (except for spaces) is + **not** eaten, meaning you can use tabs to indent further blocks of your code! + + @ Using a multi-paragraph code block + + $ ^ my_function(**argument**, **another_argument**) + + $$ Some kind of text describing the function goes here. + + $$ argument:: + This is the first argument to this example function. + + $$ another_argument:: + This is the second argument to this example function. + As you can see, it's possible to split the explanation over multiple lines as well. + + $$ @ Using this function + + $$ $ if some_variable == True: + + $$ $$ my_function(42, "The answer to everything") + + $$ > Some output goes here. + +^ Output block + + ! This block cannot have child elements! + + The output block is used to display sample output in an example. Just like the code block, it is shown exactly as it originally was, without any further formatting applied. + It is prefixed by a >, and like the code block it has a continuation character - in this case, that is >>. + + @ Using an output block + + $ ^ my_function(**argument**, **another_argument**) + + $$ Some kind of text describing the function goes here. + + $$ argument:: + This is the first argument to this example function. + + $$ another_argument:: + This is the second argument to this example function. + As you can see, it's possible to split the explanation over multiple lines as well. + + $$ @ Using this function + + $$ $ my_function(42, "The answer to everything") + + $$ > The answer to everything is 42! + + @ Using a multi-paragraph output block + + $ ^ my_function(**argument**, **another_argument**) + + $$ Some kind of text describing the function goes here. + + $$ argument:: + This is the first argument to this example function. + + $$ another_argument:: + This is the second argument to this example function. + As you can see, it's possible to split the explanation over multiple lines as well. + + $$ @ Using this function + + $$ $ my_function(42, "The answer to everything") + + $$ > The answer to everything is 42! + + $$ >> Did you know The answer to everything is 42? + +^ Exclamation block + + The exclamation block allows you to mark a block of text as "important". In the standard HTML layout, it will have a yellow-ish background, and will be prefixed + with "__Important!__". It is prefixed with an exclamation mark (!). Inline markup is applied. + + @ Using an exclamation block + + $ ^ my_function(**argument**, **another_argument**) + + $$ Some kind of text describing the function goes here. + + $$ ! Only ever use this function with the number '42'! + + $$ argument:: + This is the first argument to this example function. + + $$ another_argument:: + This is the second argument to this example function. + As you can see, it's possible to split the explanation over multiple lines as well. + + $$ @ Using this function + + $$ $ my_function(42, "The answer to everything") + + $$ > The answer to everything is 42! + + +^ Header block + + ! This block cannot have child elements! + + A header block is a generic header to indicate the start of a new section. It is treated as a separate element, not as a "container". The header blocks in ZippyDoc + work similarly to those in Markdown: they are prefixed by a hash (#), and the amount of hash characters defines what level of header it is. + + @ Using header blocks + + $ # This is a level 1 (largest) header. + + $$ ## This is a level 2 header. + + $$ ... + + $$ ####### This is a level 7 (smallest) header. + + +^ Text block + + ! This block cannot have child elements! + + A text block is any block that is not prefixed by a special character. It is shown as defined, with inline markup applied. + + +## Inline markup + +There are also various forms of inline markup that you can use in your documentation. + +^ Emphasized text + + Emphasized text is typically displayed as italic. You can emphasize text by enclosing it in two asterisks on each side. + + @ Emphasizing text + + $ This is just some text, and **this part is emphasized**. + +^ Strong text + + Strong text is typically displayed as bold. You can make text strong by enclosing it in two underscores on each side. + + @ Making text strong + + $ This is just some text, __and this part is strong__. + +^ Internal references (hyperlinks) + + Internal references are hyperlinks that point to other documents in the same documentation set. Depending on the export format (currently only HTML is supported), + the appropriate extension is automatically appended. The paths should resemble the directory structure you are storing the ZippyDoc source files in. The target + of the reference is enclosed in curly braces and prefixed with a >. If you wish to give the reference a friendly description, you can do so by appending it, + enclosed in parentheses. + + @ Referencing another documentation page + + $ You can also view the API documentation at {>api/index}. + + @ Referencing another documentation page with a friendly description + + $ You can also view the {>api/index}(API documentation). + + +^ External references (hyperlinks) + + External references are hyperlinks just like the internal references, but they refer to an external resources. The syntax is identical to that of internal references, + except for the > disappearing. Note that external references are only picked up when the text enclosed in the braces is an actual URI of some sort. + + You can also force an external reference to be created by prefixing the URI with <. This is useful when you want to for example link to a download relative to the current + page. + + @ Referencing Google + + $ You could also search {http://www.google.com/}. + + @ Referencing another documentation page with a friendly description + + $ You could also search {http://www.google.com/}(Google). + + @ Referencing a relative file that is not a ZippyDoc document + + $ You can download it by {example}(view a full example here) of a ZippyDoc source file and its result. diff --git a/example.html b/example.html new file mode 100644 index 0000000..66d696e --- /dev/null +++ b/example.html @@ -0,0 +1,187 @@ + + + + + + +

    A complete example

    Code:
    ^ my_function(**argument**, **another_argument**)
    +
    +	Some kind of text describing the function goes here. `Also some mono-spaced text.`
    +
    +	! Only ever use this function with the number '42'!
    +
    +	argument::
    +		This is the first argument to this example function.
    +
    +	another_argument::
    +		This is the second argument to this example function.
    +		As you can see, it's possible to split the explanation over multiple lines as well.
    +		We can also add an {>documentation}(internal link) and an {http://google.com/}(external link).
    +
    +	@ Using this function
    +
    +		$ if some_variable == True:
    +
    +		$$	my_function(42, "The answer to everything")
    +
    +		> The answer to everything is 42!
    +
    +		>>	Did you know The answer to everything is 42?

    Result

    + + diff --git a/example.zpy b/example.zpy new file mode 100644 index 0000000..bd4110e --- /dev/null +++ b/example.zpy @@ -0,0 +1,51 @@ +# A complete example + +$ ^ my_function(**argument**, **another_argument**) + +$$ Some kind of text describing the function goes here. `Also some mono-spaced text.` + +$$ ! Only ever use this function with the number '42'! + +$$ argument:: + This is the first argument to this example function. + +$$ another_argument:: + This is the second argument to this example function. + As you can see, it's possible to split the explanation over multiple lines as well. + We can also add an {>documentation}(internal link) and an {http://google.com/}(external link). + +$$ @ Using this function + +$$ $ if some_variable == True: + +$$ $$ my_function(42, "The answer to everything") + +$$ > The answer to everything is 42! + +$$ >> Did you know The answer to everything is 42? + +## Result + +^ my_function(**argument**, **another_argument**) + + Some kind of text describing the function goes here. `Also some mono-spaced text.` + + ! Only ever use this function with the number '42'! + + argument:: + This is the first argument to this example function. + + another_argument:: + This is the second argument to this example function. + As you can see, it's possible to split the explanation over multiple lines as well. + We can also add an {>documentation}(internal link) and an {http://google.com/}(external link). + + @ Using this function + + $ if some_variable == True: + + $$ my_function(42, "The answer to everything") + + > The answer to everything is 42! + + >> Did you know The answer to everything is 42? diff --git a/index.html b/index.html new file mode 100644 index 0000000..0a970d8 --- /dev/null +++ b/index.html @@ -0,0 +1,177 @@ + + + + + + +

    ZippyDoc

    Hi, this is the website of ZippyDoc, a compact, light-weight and human-readable format for documenting code, APIs, and other things, that can be easily converted to HTML.
    It is designed primarily to be simple to use (unlike complex markup languages like reStructuredText), and very code-oriented (unlike other simple markup languages like Markdown). You will probably learn the entire syntax in about 10 minutes.
    ZippyDoc (both the format and the parser) are licensed under the WTFPL, meaning you can basically do with it whatever you want, and reuse it in any fashion you see fit. I hope it will help you write nicer, easier, and more complete documentation!
    While ZippyDoc is technically intended for documentation, I decided to whip up a simple index page in ZippyDoc as well - you're looking at it! :)

    What does the ZippyDoc format look like?

    Code:
    ^ my_function(argument1, argument2)
    +
    +	! This is just an example!
    +
    +	This is a function.
    +
    +	argument1::
    +		This is the first argument.
    +
    +	argument2::
    +		This is the second argument.
    +
    +	@ How to call my_function
    +
    +		$ my_function("ZippyDoc", "awesome")
    +
    +		> "ZippyDoc is awesome!"
    Result:

    Documentation

    The documentation for ZippyDoc can be found here.

    Downloading ZippyDoc

    ZippyDoc is still in a pretty messy stage, but it should already work reliably according to the current documentation. GitHub repository is coming soon, until that time you can download the conversion script here. It's a Python script, so you'll need a Python interpreter of some sort. No dependencies are necessary, it only uses standard library functionality. Simply run it with all files you wish to convert as arguments, and it will convert each of them into a file with the same name, but a .html extension instead of the original extension. It's strongly recommended to name your ZippyDoc source files with the .zpy extension.
    + + diff --git a/index.zpy b/index.zpy new file mode 100644 index 0000000..436d40e --- /dev/null +++ b/index.zpy @@ -0,0 +1,62 @@ +# ZippyDoc + +Hi, this is the website of ZippyDoc, a compact, light-weight and human-readable format for documenting code, APIs, and other things, that can be easily converted to HTML. + +It is designed primarily to be simple to use (unlike complex markup languages like reStructuredText), and very code-oriented (unlike other simple markup languages like Markdown). +You will probably learn the entire syntax in about 10 minutes. + +ZippyDoc (both the format and the parser) are licensed under the {http://www.wtfpl.net/}(WTFPL), meaning you can basically do with it whatever you want, and reuse it in any +fashion you see fit. I hope it will help you write nicer, easier, and more complete documentation! + +While ZippyDoc is technically intended for documentation, I decided to whip up a simple index page in ZippyDoc as well - you're looking at it! :) + +## What does the ZippyDoc format look like? + +$ ^ my_function(argument1, argument2) + +$$ ! This is just an example! + +$$ This is a function. + +$$ argument1:: + This is the first argument. + +$$ argument2:: + This is the second argument. + +$$ @ How to call my_function + +$$ $ my_function("ZippyDoc", "awesome") + +$$ > "ZippyDoc is awesome!" + +####### Result: + +^ my_function(argument1, argument2) + + ! This is just an example! + + This is a function. + + argument1:: + This is the first argument. + + argument2:: + This is the second argument. + + @ How to call my_function + + $ my_function("ZippyDoc", "awesome") + + > "ZippyDoc is awesome!" + +## Documentation + +The documentation for ZippyDoc can be found {>documentation}(here). + +## Downloading ZippyDoc + +ZippyDoc is still in a pretty messy stage, but it should already work reliably according to the current documentation. GitHub repository is coming soon, until that time you can +{ Date: Mon, 22 Apr 2013 01:04:55 +0200 Subject: [PATCH 7/9] Documentation fix --- documentation.zpy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation.zpy b/documentation.zpy index cae8ac6..7304ec2 100644 --- a/documentation.zpy +++ b/documentation.zpy @@ -286,7 +286,7 @@ There are also various forms of inline markup that you can use in your documenta $ You could also search {http://www.google.com/}. - @ Referencing another documentation page with a friendly description + @ Referencing Google with a friendly description $ You could also search {http://www.google.com/}(Google). From b97cec6aaad5a9fa01dc3df4e0d25f0c60eb8093 Mon Sep 17 00:00:00 2001 From: Sven Slootweg Date: Mon, 22 Apr 2013 01:06:28 +0200 Subject: [PATCH 8/9] Reorganize source tree and add a setup script --- .gitignore | 3 ++ MANIFEST.in | 1 + setup.py | 49 +++++++++++++++++++ documentation.html => site/documentation.html | 0 documentation.zpy => site/documentation.zpy | 0 example.html => site/example.html | 0 example.zpy => site/example.zpy | 0 index.html => site/index.html | 2 +- index.zpy => site/index.zpy | 6 +-- {zippydoc => src/zippydoc}/__init__.py | 0 {zippydoc => src/zippydoc}/block_markup.py | 0 .../zippydoc/data/template.html | 0 {zippydoc => src/zippydoc}/document.py | 0 .../zippydoc}/transformation_ruleset.py | 0 {zippydoc => src/zippydoc}/value.py | 0 zpy2html.py => zpy2html | 11 ++++- 16 files changed, 66 insertions(+), 6 deletions(-) create mode 100644 MANIFEST.in create mode 100644 setup.py rename documentation.html => site/documentation.html (100%) rename documentation.zpy => site/documentation.zpy (100%) rename example.html => site/example.html (100%) rename example.zpy => site/example.zpy (100%) rename index.html => site/index.html (85%) rename index.zpy => site/index.zpy (70%) rename {zippydoc => src/zippydoc}/__init__.py (100%) rename {zippydoc => src/zippydoc}/block_markup.py (100%) rename template.html => src/zippydoc/data/template.html (100%) rename {zippydoc => src/zippydoc}/document.py (100%) rename {zippydoc => src/zippydoc}/transformation_ruleset.py (100%) rename {zippydoc => src/zippydoc}/value.py (100%) rename zpy2html.py => zpy2html (94%) mode change 100644 => 100755 diff --git a/.gitignore b/.gitignore index 0d20b64..cec05fb 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ *.pyc +build/ +dist/ +zippydoc.egg-info/ diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..c011d97 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +include src/zippydoc/data/* diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..920e824 --- /dev/null +++ b/setup.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python + +""" +distutils/setuptools install script. See inline comments for packaging documentation. +""" + +import os +import sys + +try: + from setuptools import setup + # hush pyflakes + setup +except ImportError: + from distutils.core import setup + +try: + from distutils.command.build_py import build_py_2to3 as build_py +except ImportError: + from distutils.command.build_py import build_py + +packages = ['zippydoc'] + +package_dir = {"zippydoc": "src/zippydoc"} + +package_data = {"zippydoc": ["data/template.html"]} + +scripts = [ + 'zpy2html' +] + +print repr(package_data) + +setup( + name='zippydoc', + version='1.0', + maintainer='Sven Slootweg', + maintainer_email='admin@cryto.net', + description='Documentation markup language and library, including HTML converter.', + url='http://www.cryto.net/zippydoc', + packages=packages, + package_dir=package_dir, + package_data=package_data, + include_package_data=True, + scripts=scripts, + install_requires=['argparse'], + cmdclass={'build_py': build_py} +) + diff --git a/documentation.html b/site/documentation.html similarity index 100% rename from documentation.html rename to site/documentation.html diff --git a/documentation.zpy b/site/documentation.zpy similarity index 100% rename from documentation.zpy rename to site/documentation.zpy diff --git a/example.html b/site/example.html similarity index 100% rename from example.html rename to site/example.html diff --git a/example.zpy b/site/example.zpy similarity index 100% rename from example.zpy rename to site/example.zpy diff --git a/index.html b/site/index.html similarity index 85% rename from index.html rename to site/index.html index 0a970d8..c21e05a 100644 --- a/index.html +++ b/site/index.html @@ -172,6 +172,6 @@ $ my_function("ZippyDoc", "awesome") - > "ZippyDoc is awesome!"Result:

    Documentation

    The documentation for ZippyDoc can be found here.

    Downloading ZippyDoc

    ZippyDoc is still in a pretty messy stage, but it should already work reliably according to the current documentation. GitHub repository is coming soon, until that time you can download the conversion script here. It's a Python script, so you'll need a Python interpreter of some sort. No dependencies are necessary, it only uses standard library functionality. Simply run it with all files you wish to convert as arguments, and it will convert each of them into a file with the same name, but a .html extension instead of the original extension. It's strongly recommended to name your ZippyDoc source files with the .zpy extension.
    + > "ZippyDoc is awesome!"Result:

    Documentation

    The documentation for ZippyDoc can be found here.

    Downloading ZippyDoc

    ZippyDoc is now a PyPi package! To install it, make sure you have pip installed, and run pip install zippydoc. You can then use the zpy2html command anywhere, to convert your ZippyDoc source files to HTML. The GitHub repository can be found here.
    diff --git a/index.zpy b/site/index.zpy similarity index 70% rename from index.zpy rename to site/index.zpy index 436d40e..dfe11c8 100644 --- a/index.zpy +++ b/site/index.zpy @@ -56,7 +56,5 @@ The documentation for ZippyDoc can be found {>documentation}(here). ## Downloading ZippyDoc -ZippyDoc is still in a pretty messy stage, but it should already work reliably according to the current documentation. GitHub repository is coming soon, until that time you can -{ Date: Mon, 22 Apr 2013 01:09:04 +0200 Subject: [PATCH 9/9] Reflect documentation fix in rendered version --- site/documentation.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/documentation.html b/site/documentation.html index 3f4c271..1110b69 100644 --- a/site/documentation.html +++ b/site/documentation.html @@ -272,7 +272,7 @@ ... -####### This is a level 7 (smallest) header.

    Inline markup

    There are also various forms of inline markup that you can use in your documentation.

    Special tags

    Currently there is only one special tag. Special tags can be inserted anywhere in the document to insert a generated element.

    Inline markup

    There are also various forms of inline markup that you can use in your documentation.

    Special tags

    Currently there is only one special tag. Special tags can be inserted anywhere in the document to insert a generated element.