Skip to content

Instantly share code, notes, and snippets.

@x-projs
Created December 30, 2019 10:26
Show Gist options
  • Save x-projs/c1d589e178ce0791df440b1d0453c736 to your computer and use it in GitHub Desktop.
Save x-projs/c1d589e178ce0791df440b1d0453c736 to your computer and use it in GitHub Desktop.
Preprocessor for mdbook to generate blockdiag.
# 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