Created
December 30, 2019 10:26
-
-
Save x-projs/c1d589e178ce0791df440b1d0453c736 to your computer and use it in GitHub Desktop.
Preprocessor for mdbook to generate blockdiag.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Preprocessor for mdbook to generate blockdiag. | |
# By [email protected], MIT License | |
# | |
# Convert the following code in .md to svg: | |
# | |
# ``` | |
# seqdiag { | |
# A --> B | |
# B --> C | |
# } | |
# ``` | |
# | |
# Support actdiag, blockdiag, nwdiag, packetdiag, rackdiag and seqdiag. More examples: http://blockdiag.com/ | |
# | |
# Add the following lines in book.toml to use it: | |
# | |
# [preprocessor.blockdiag] | |
# command = "python mdbook-blockdiag.py" | |
# renderer = ["html"] | |
import datetime | |
import json | |
import os | |
import re | |
import sys | |
import actdiag.parser, actdiag.builder, actdiag.drawer | |
import blockdiag.parser, blockdiag.builder, blockdiag.drawer | |
import nwdiag.parser, nwdiag.builder, nwdiag.drawer | |
import packetdiag.parser, packetdiag.builder, packetdiag.drawer | |
import rackdiag.parser, rackdiag.builder, rackdiag.drawer | |
import seqdiag.parser, seqdiag.builder, seqdiag.drawer | |
def processBookItem(src_path, item): | |
if 'Chapter' in item: | |
processChapter(src_path, item['Chapter']) | |
def processChapter(src_path, ch): | |
file_path = src_path + "/" + ch['path'] | |
# parse content | |
while True: | |
group = re.search(r'^\s*```\s*(actdiag|blockdiag|nwdiag|packetdiag|rackdiag|seqdiag)\s*(\{.*?\})\s*```\s*$', ch['content'], re.DOTALL|re.MULTILINE) | |
if group: | |
try: | |
# Get svg | |
diagModule = sys.modules[group.group(1)] | |
tree = diagModule.parser.parse_string(group.group(2)) | |
diagram = diagModule.builder.ScreenNodeBuilder.build(tree) | |
draw = diagModule.drawer.DiagramDraw('SVG', diagram) | |
draw.draw() | |
svg = draw.save() | |
# Remove svg header | |
svg = re.search('<svg .*</svg>', draw.save(), re.DOTALL).group(0) | |
# Handle `// max_img_width = xxxx;` | |
# User can use this way to set the max width of svg. | |
maxWidth = re.search(r'//\s*max_img_width\s*=\s*(\d+)\s*;', group.group(2)) | |
if maxWidth: | |
svg = svg.replace('<svg ', '<svg style="max-width: {}px;" '.format(maxWidth.group(1)), 1) | |
# Insert svg into content | |
ch['content'] = ch['content'].replace(group.group(0), '\n' + svg + '\n', 1) | |
except: | |
print >> sys.stderr, "{} [WARN] Parse {} in {} failed, ignore it.".format(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), group.group(1), file_path) | |
break | |
else: | |
break | |
# process sub items | |
for item in ch['sub_items']: | |
processBookItem(src_path, item) | |
def main(): | |
if 'supports' in sys.argv: | |
sys.exit(0) | |
(config, book) = json.loads(sys.stdin.readlines()[0]) | |
src_path = config['config']['book']['src'] | |
sections = book['sections'] | |
for item in sections: | |
processBookItem(src_path, item) | |
print json.dumps(book) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment