├── .gitignore
├── README.md
├── examples
├── configs.py
├── example.py
└── test.md
└── mdx_graphviz.py
/.gitignore:
--------------------------------------------------------------------------------
1 | *~
2 | *.pyc
3 | *.html
4 | *.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### Python-Markdown-Graphviz
2 |
3 | The goal of this library is to support embedding graphviz graphs inside
4 | Markdown documents.
5 |
6 | Requires:
7 |
8 | * Python (tested on 2.5, 2.6, not sure about 2.4 off hand)
9 | * Graphviz
10 | * ubuntu: ``apt-get install graphviz``
11 | * others: download at [graphviz.org](graphviz.org)
12 | * Python-Markdown
13 | * ``easy_install Markdown``
14 |
15 | Read the ``examples/example.py`` for a simple example.
16 |
17 | Some overview is available [in this blog post][blog].
18 |
19 | [blog]: http://lethain.com/entry/2010/jan/16/a-python-markdown-extension-for-embedding-graphviz/ "A Python Markdown Extension for Embedding Graphviz"
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/examples/configs.py:
--------------------------------------------------------------------------------
1 | import markdown
2 |
3 | fin = open("test.md", 'r')
4 | txt = fin.read()
5 | fin.close()
6 | md = markdown.Markdown(
7 | extensions=['graphviz'],
8 | extension_configs={'graphviz':
9 | {'FORMAT':'gif'}
10 | },
11 | )
12 | print md.convert(txt)
13 |
--------------------------------------------------------------------------------
/examples/example.py:
--------------------------------------------------------------------------------
1 | import markdown
2 |
3 | fin = open("test.md", 'r')
4 | txt = fin.read()
5 | fin.close()
6 | md = markdown.Markdown(extensions=['graphviz'])
7 | print md.convert(txt)
8 |
--------------------------------------------------------------------------------
/examples/test.md:
--------------------------------------------------------------------------------
1 | # Test
2 |
3 |
4 | digraph a {
5 | a -> b;
6 | }
7 |
8 |
9 | * a
10 | * b
11 | * c
12 |
13 |
14 |
--------------------------------------------------------------------------------
/mdx_graphviz.py:
--------------------------------------------------------------------------------
1 | """
2 | ### Markdown-Python-Graphviz
3 |
4 | This module is an extention to [Python-Markdown][pymd] which makes it
5 | possible to embed [Graphviz][gv] syntax into Markdown documents.
6 |
7 | ### Requirements
8 |
9 | Using this module requires:
10 | * Python-Markdown
11 | * Graphviz (particularly ``dot``)
12 |
13 | ### Syntax
14 |
15 | Wrap Graphviz definitions within a dot/neato/dotty/lefty tag.
16 |
17 | An example document:
18 |
19 | This is some text above a graph.
20 |
21 |
22 | digraph a {
23 | nodesep=1.0;
24 | rankdir=LR;
25 | a -> b -> c ->d;
26 | }
27 |
28 |
29 | Some other text between two graphs.
30 |
31 |
32 | some graph in neato...
33 |
34 |
35 | This is also some text below a graph.
36 |
37 | Note that the opening and closing tags should come at the beginning of
38 | their lines and should be immediately followed by a newline.
39 |
40 | ### Usage
41 |
42 | import markdown
43 | md = markdown.Markdown(
44 | extensions=['graphviz'],
45 | extension_configs={'graphviz' : {'DOT','/usr/bin/dot'}}
46 | )
47 | return md.convert(some_text)
48 |
49 |
50 | [pymd]: http://www.freewisdom.org/projects/python-markdown/ "Python-Markdown"
51 | [gv]: http://www.graphviz.org/ "Graphviz"
52 |
53 | """
54 | import markdown, re, markdown.preprocessors, subprocess
55 |
56 | class GraphvizExtension(markdown.Extension):
57 | def __init__(self, configs):
58 | self.config = {'FORMAT':'png', 'BINARY_PATH':"", 'WRITE_IMGS_DIR':"", "BASE_IMG_LINK_DIR":""}
59 | for key, value in configs:
60 | self.config[key] = value
61 |
62 | def reset(self):
63 | pass
64 |
65 | def extendMarkdown(self, md, md_globals):
66 | "Add GraphvizExtension to the Markdown instance."
67 | md.registerExtension(self)
68 | self.parser = md.parser
69 | md.preprocessors.add('graphviz', GraphvizPreprocessor(self), '_begin')
70 |
71 | class GraphvizPreprocessor(markdown.preprocessors.Preprocessor):
72 | "Find all graphviz blocks, generate images and inject image link to generated images."
73 |
74 | def __init__ (self, graphviz):
75 | self.graphviz = graphviz
76 | self.formatters = ["dot", "neato", "lefty", "dotty"]
77 |
78 | def run(self, lines):
79 | start_tags = [ "<%s>" % x for x in self.formatters ]
80 | end_tags = [ "%s>" % x for x in self.formatters ]
81 | graph_n = 0
82 | new_lines = []
83 | block = []
84 | in_block = None
85 | for line in lines:
86 | if line in start_tags:
87 | assert(block == [])
88 | in_block = self.extract_format(line)
89 | elif line in end_tags:
90 | new_lines.append(self.graph(graph_n, in_block, block))
91 | graph_n = graph_n + 1
92 | block = []
93 | in_block = None
94 | elif in_block in self.formatters:
95 | block.append(line)
96 | else:
97 | new_lines.append(line)
98 | assert(block == [])
99 | return new_lines
100 |
101 | def extract_format(self, tag):
102 | format = tag[1:-1]
103 | assert(format in self.formatters)
104 | return format
105 |
106 | def graph(self, n, type, lines):
107 | "Generates a graph from lines and returns a string containing n image link to created graph."
108 | assert(type in self.formatters)
109 | cmd = "%s%s -T%s" % (self.graphviz.config["BINARY_PATH"],
110 | type,
111 | self.graphviz.config["FORMAT"])
112 | p = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, close_fds=True)
113 | #(child_stdin, child_stdout) = (p.stdin, p.stdout)
114 | p.stdin.write("\n".join(lines))
115 | p.stdin.close()
116 | p.wait()
117 | filepath = "%s%s.%s" % (self.graphviz.config["WRITE_IMGS_DIR"], n, self.graphviz.config["FORMAT"])
118 | fout = open(filepath, 'w')
119 | fout.write(p.stdout.read())
120 | fout.close()
121 | output_path = "%s%s.%s" % (self.graphviz.config["BASE_IMG_LINK_DIR"], n, self.graphviz.config["FORMAT"])
122 | return "" % (n, output_path)
123 |
124 | def makeExtension(configs=None) :
125 | return GraphvizExtension(configs=configs)
126 |
--------------------------------------------------------------------------------