diff --git a/Makefile b/Makefile
index 5f7ddd3ee3fce10fdc3a29c9c11f237176cd1f28..3cc51bd07e182a353b1fe6bd1d5a699c422a7032 100644
--- a/Makefile
+++ b/Makefile
@@ -243,6 +243,8 @@ submodules = $(sort $(shell test -d .git && (git config --file .gitmodules --get
 
 dist: $(debsrc)
 
+# Determine the version number of this build. We get this from m_pd.h.
+PD_L2ORK_VERSION := $(shell grep PD_L2ORK_VERSION pd/src/m_pd.h | sed 's|^.define *PD_L2ORK_VERSION *"\(.*\)".*|\1|')
 # Determine the build version which needs git to be computed, so we can't do
 # it in a stand-alone build from a tarball.
 PD_BUILD_VERSION := $(shell test -d .git && (git log -1 --format=%cd --date=short | sed -e 's/-//g'))-rev.$(shell test -d .git && git rev-parse --short HEAD)
@@ -259,6 +261,12 @@ $(debsrc):
 # Pre-generate and put s_version.h into the tarball (see above; the build
 # version is generated using git which can't be done outside the git repo).
 	sed 's|^\(#define PD_BUILD_VERSION "\).*"|\1$(PD_BUILD_VERSION)"|' pd/src/s_version.h.in > $(debdist)/pd/src/s_version.h
+# Pre-generate the markdown and html docs so that they will be included in the
+# source. This means that we don't need any special tools as a build
+# dependency, which makes live a lot easier.
+	make -C packages/gendoc version="$(PD_L2ORK_VERSION)" build_version="$(PD_BUILD_VERSION)"
+	mv packages/gendoc/{ReadMe,Welcome}-*.{md,html} $(debdist)/packages/gendoc
+	make -C packages/gendoc clean
 # Create the source tarball.
 	tar cfz $(debsrc) $(debdist)
 	rm -rf $(debdist)
diff --git a/README.md b/README.md
index 16e0d9e330f6d52cb130f68469c52be9f2de95b5..e355029787e6a08bc4acbd75436ceb2ddc875bb8 100644
--- a/README.md
+++ b/README.md
@@ -162,7 +162,8 @@ Hard drive space required: *roughly 2.5 GB*
              mda-lv2 libmp3lame-dev libspeex-dev libgsl0-dev \
              portaudio19-dev liblua5.3-dev python-dev libsmpeg0 libjpeg62-turbo \
              flite1-dev libgsm1-dev libgtk2.0-dev git libstk0-dev \
-             libfluidsynth-dev fluid-soundfont-gm byacc
+             libfluidsynth-dev fluid-soundfont-gm byacc \
+             python3-markdown
 
 2. The gui toolkit may require installing the following extra dependencies
 
@@ -200,6 +201,7 @@ Hard drive space required: *roughly 2 GB*
         brew install libtool
         brew install fftw
         brew install python
+        brew install python-markdown
         brew install lua
         brew install fluidsynth
         brew install lame
@@ -274,6 +276,8 @@ since it will usually contain spaces, making the build fail.
           mingw-w64-i686-lua mingw-w64-i686-toolchain \
           mingw-w64-i686-libjpeg-turbo \
           mingw-w64-i686-speex \
+          mingw-w64-i686-python \
+          mingw-w64-i686-python-markdown \
           rsync unzip wget
 
 5. Download the source code *(3-6 minutes)*  
@@ -315,6 +319,8 @@ convenience:
           mingw-w64-x86_64-lua mingw-w64-x86_64-toolchain \
           mingw-w64-x86_64-libjpeg-turbo \
           mingw-w64-x86_64-speex \
+          mingw-w64-x86_64-python \
+          mingw-w64-x86_64-python-markdown \
           rsync unzip wget
 
 - Use the MSYS2 MinGW 64-bit shell (rather than the 32-bit shell) to do the
diff --git a/debuild/Makefile b/debuild/Makefile
index 053f9746fddfd7b068c89bacfdf8f0b236e50907..75f89503a8569414599f823e6a8e9925c11b6443 100644
--- a/debuild/Makefile
+++ b/debuild/Makefile
@@ -32,9 +32,15 @@
 # 4. Run 'make debclean' to get rid of any files that were created in steps 2
 # and 3.
 
+# Determine the version number of this build. We get this from m_pd.h.
+PD_L2ORK_VERSION := $(shell grep PD_L2ORK_VERSION ../pd/src/m_pd.h | sed 's|^.define *PD_L2ORK_VERSION *"\(.*\)".*|\1|')
+# Determine the build version which needs git to be computed, so we can't do
+# it in a stand-alone build from a tarball
+PD_BUILD_VERSION := $(shell git log -1 --format=%cd --date=short | sed -e 's/-//g')-rev.$(shell git rev-parse --short HEAD)
+
 # The Debian version gets derived from the date and serial number of the last
 # commit. You can print it with 'make debversion'.
-debversion = $(shell grep PD_L2ORK_VERSION ../pd/src/m_pd.h | sed 's|^.define *PD_L2ORK_VERSION *"\(.*\)".*|\1|')+git$(shell git rev-list --count HEAD)+$(shell git rev-parse --short HEAD)
+debversion = $(PD_L2ORK_VERSION)+git$(shell git rev-list --count HEAD)+$(shell git rev-parse --short HEAD)
 # Debian revision number of the package.
 debrevision = 1
 # Source tarball and folder.
@@ -97,10 +103,6 @@ deb-us:
 debsrc-us:
 	$(MAKE) deb DEBUILD_FLAGS="-S -d -us -uc"
 
-# Determine the build version which needs git to be computed, so we can't do
-# it in a stand-alone build from a tarball.
-PD_BUILD_VERSION := $(shell git log -1 --format=%cd --date=short | sed -e 's/-//g')-rev.$(shell git rev-parse --short HEAD)
-
 $(debsrc):
 	rm -rf $(debdist)
 # Make sure that the submodules are initialized.
@@ -112,6 +114,13 @@ $(debsrc):
 # Pre-generate and put s_version.h into the tarball (see above; the build
 # version is generated using git which can't be done outside the git repo).
 	sed 's|^\(#define PD_BUILD_VERSION "\).*"|\1$(PD_BUILD_VERSION)"|' ../pd/src/s_version.h.in > $(debdist)/pd/src/s_version.h
+# Pre-generate the markdown and html docs so that they will be included in the
+# source. This means that we don't need any special tools as a build
+# dependency, which makes live a lot easier.
+	make -C ../packages/gendoc version="$(PD_L2ORK_VERSION)" build_version="$(PD_BUILD_VERSION)"
+	mv ../packages/gendoc/*-Linux* $(debdist)/packages/gendoc
+	make -C ../packages/gendoc clean
+	ls -l $(debdist)/packages/gendoc/*.html
 # Create the source tarball.
 	tar cfz $(debsrc) $(debdist)
 	rm -rf $(debdist)
diff --git a/debuild/debian/rules b/debuild/debian/rules
index d8c498f3f007b25e07521b149956bd167a71ae33..2cf8bac94b45dbc56a8e47f7d6fccfe977c40fef 100755
--- a/debuild/debian/rules
+++ b/debuild/debian/rules
@@ -44,6 +44,9 @@ override_dh_auto_build:
 # Copy the nw.js sources to where purr-data wants them.
 	@echo "DEB_HOST_ARCH = $(shell dpkg-architecture -qDEB_HOST_ARCH)"
 	tar -xf debian/nwjs/$(nwjspkg)-$(arch).tar.gz && rm -rf pd/nw/nw && mv $(nwjsdir)-$(arch) pd/nw/nw
+# Make sure that the html docs in packages/gendoc are current so that we don't
+# accidentally try to rebuild them.
+	cd packages/gendoc && touch *-Linux*.html
 	cd l2ork_addons && (export V=0 inst_dir=$(prefix); ./tar_em_up.sh -Bn)
 	make check prefix=$(prefix)
 
diff --git a/packages/Makefile b/packages/Makefile
index 4c1c9a104bedafcf9274f22a8521d8b80748c30f..94bfe7b5648a26c76be88b764028fb7187b84612 100644
--- a/packages/Makefile
+++ b/packages/Makefile
@@ -235,21 +235,20 @@ license_install:
 
 
 
+# AG: Replaced the previous jumble of echo commands with document generation
+# from Markdown using awk for preprocessing and python-markdown for
+# formatting. Also updated the document content which was really outdated. You
+# can find all this stuff including the Markdown source in the gendoc
+# subdirectory.
+
+osname = $(shell uname -s|sed 's/\([[:alpha:]]*\).*/\1/')
+
 WELCOME_FILE = $(DESTDIR)$(manualsdir)/$(PD_NAME)/Welcome.html
 welcome_install:
 	install -d $(DESTDIR)$(manualsdir)/$(PD_NAME)
-	-rm $(WELCOME_FILE)
-	touch $(WELCOME_FILE)
-	echo "<html><head>" >> $(WELCOME_FILE)
-	echo "<link rel=\"stylesheet\" type=\"text/css\" href=\"http://puredata.org/ploneCustom.css\" />" >> $(WELCOME_FILE)
-	echo "</head>" >> $(WELCOME_FILE)
-	echo "<body><p><p>" >> $(WELCOME_FILE)
-	echo "<h2>Pd-l2ork version $(PD_L2ORK_VERSION) ($(PD_BUILD_VERSION))</h2>" >> $(WELCOME_FILE)
-	echo "<p>Pd-l2ork was written by Ivica Bukvic and Jonathan Wilkes. It is a fork of Hans-Christoph Steiner's Pd-extended, which in turn is based on Miller S. Puckette's Pd. The included Pd abstractions and externals are the work of many people whose contributions are gratefully acknowledged.</p>" >> $(WELCOME_FILE)
-	echo "<font size=\"-1\">" >> $(WELCOME_FILE)
-	echo "<p>`grep -A9 ACKNOWLEDG $(pd_src)/README.txt`</p>" >> $(WELCOME_FILE)
-	echo "</font>" >> $(WELCOME_FILE)
-	echo "</body></html>" >> $(WELCOME_FILE)
+	rm -f $(WELCOME_FILE)
+	$(MAKE) -C gendoc Welcome-$(osname).html version="$(PD_L2ORK_VERSION)" build_version="$(PD_BUILD_VERSION)"
+	cp gendoc/Welcome-$(osname).html $(WELCOME_FILE)
 
 
 
@@ -257,102 +256,9 @@ README_FILE = $(DESTDIR)$(manualsdir)/$(PD_NAME)/ReadMe.html
 readme_install: 
 	install -d $(DESTDIR)$(manualsdir)/$(PD_NAME)
 	echo $(CYCLONE_RELEASE)
-	-rm $(README_FILE)
-	touch $(README_FILE)
-	echo "<html>" >> $(README_FILE)
-	echo "<head>" >> $(README_FILE)
-	echo "<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" />" >> $(README_FILE)
-	echo "<link rel=\"stylesheet\" type=\"text/css\" href=\"http://puredata.org/plone.css\" />" >> $(README_FILE)
-	echo "</head>" >> $(README_FILE)
-	echo "<body>" >> $(README_FILE)
-	echo "<h2>Pd-l2ork version $(PD_L2ORK_VERSION) ($(PD_BUILD_VERSION))</h2>" 	>> $(README_FILE)
-	echo "<p>Pd is a real-time, graphical programming language for media processing created by Miller S. Puckette.  It provides an environment for audio analysis, synthesis, and processing, with a rich set of multimedia capabilities.  You can get Pd for Linux, Windows, MacOS X, BSD, or IRIX.</p>" >> $(README_FILE)
-	echo "<p>Pd-l2ork is a version of Pd based on Hans-Christoph Steiner's Pd-extended which features many bugfixes and enhancements, especially in the user interface.  Pd-l2ork was created by Ivica Ico Bukvic and is maintained by a team of volunteers including Jonathan Wilkes who ported it to the Mac and Windows.  It is available for Linux, Windows and MacOS X.</p>" >> $(README_FILE)
-	echo "<p>For general information about Pd, go to: <a href=\"http://puredata.org\" target=\"pd\">http://puredata.org</a>.  More information about Pd-l2ork can be found on the <a href=\"http://l2ork.music.vt.edu/main/make-your-own-l2ork/software/\" target=\"pd-l2ork\">Pd-l2ork website</a>.</p>" >> $(README_FILE)
-	echo "<h3>Installation</h3>" >> $(README_FILE)	
-ifeq ($(OS_NAME),linux)
-	echo "<p>Links to Pd-l2ork packages for various Linux distributions are available on the <a href=\"http://l2ork.music.vt.edu/main/make-your-own-l2ork/software/\" target=\"pd-l2ork\">Pd-l2ork website</a>.</p>" >> $(README_FILE)
-	echo "<p>If you're running Ubuntu or Arch, you may also want to check out Albert Gräf's packages on Launchpad and the Arch User Repositories (AUR).  Please check his corresponding <a href=\"https://l2orkaur.bitbucket.io/\" target=\"l2orkaur\">Bitbucket</a> <a href=\"https://l2orkubuntu.bitbucket.io/\" target=\"l2orkubuntu\">pages</a> for details.</p>" >> $(README_FILE)
-endif
-ifeq ($(OS_NAME),darwin)
-	echo "<p>To install Pd-l2ork, drag the $(APPLICATION_NAME).app into your <b>/Applications</b> folder or to the shortcut in the disk image.</p>" >> $(README_FILE)
-	echo "<p>By default, most of the included libraries are loaded at startup.  To change this, set your own preferences in the <b>Startup</b> tab of the Preferences dialog.  If you want to reset Pd-l2ork to the default preferences, remove the Pd-l2ork preferences file <strong>~/Library/Preferences/org.puredata.pd-l2ork.plist</strong> (<code>~</code> means your home folder), or run the following command in the Terminal.app: </p><p><code>rm ~/Library/Preferences/org.puredata.pd-l2ork.plist</code></p>" >> $(README_FILE)
-	echo "<p>If you want to use PDP on Mac OS X, you may have to install X11.  See <a href=\"http://puredata.info/docs/faq/macosx\" target=\"_blank\">How do I install Pd on MacOS X?</a> for details.</p>" >> $(README_FILE)
-endif
-ifeq ($(OS_NAME),windows)
-	echo "<p>To make sure that all of the included libraries are loaded when Pd runs, " >> $(README_FILE)
-	echo "double-click <code>C:\Program Files\pd\pd-settings.reg</code> to import the settings to the registry.  WARNING: this will overwrite any existing Pd preferences!</p>" >> $(README_FILE)
-	echo "<h3>ASIO4ALL</h3>" >> $(README_FILE)	
-	echo "<p><a href=\"http://www.asio4all.com/\" target=\"_blank\">ASIO4ALL</a> is a cost-free <a href=\"http://en.wikipedia.org/wiki/Audio_Stream_Input/Output\" target=\"_blank\">ASIO</a> audio driver.  Is it highly recommended for use with Pd.  Download and install it, then when you launch Pd, choose the <strong>ASIO</strong> option from the <strong>Media</strong> menu.  Using ASIO4ALL should mean less crashes and troubles, as well as better audio performance." >> $(README_FILE)
-	echo "</p>" >> $(README_FILE)
-endif
-	echo "<h3>Installing Externals, Objects, and Help files</h3>" >> $(README_FILE)
-	echo "<p>" >> $(README_FILE)
-	echo "If you would like to install other externals, objects, help files, etc. there are special folders that Pd-l2ork uses, which are listed below.  If the folder does not exist, you should create it.  You can find out more details about this by reading this FAQ:  <a href=\"http://puredata.info/docs/faq/how-do-i-install-externals-and-help-files\" target=\"_blank\">How do I install externals and help files?</a>." >> $(README_FILE)
-	echo "<dl>" >> $(README_FILE)
-ifeq ($(OS_NAME),darwin)
-	echo "<dt>Only for the current user account</dt>" >> $(README_FILE)
-	echo "<dd>~/Library/Pd-l2ork</dd>" >> $(README_FILE)
-	echo "<dt>For all user accounts on the computer</dt>" >> $(README_FILE)
-	echo "<dd>/Library/Pd-l2ork</dd>" >> $(README_FILE)
-endif
-ifeq ($(OS_NAME),linux)
-	echo "<dt>Only for the current user account</dt>" >> $(README_FILE)
-	echo "<dd>~/pd-l2ork-externals/</dd>" >> $(README_FILE)
-	echo "<dt>For all user accounts on the computer</dt>" >> $(README_FILE)
-	echo "<dd>/usr/local/lib/pd-l2ork-externals</dd>" >> $(README_FILE)
-endif
-ifeq ($(OS_NAME),windows)
-	echo "<dt>Only for the current user account</dt>" >> $(README_FILE)
-	echo "<dd><a href=\"file:///%UserProfile%/Application%20Data\">%UserProfile%\Application Data\Pd-l2ork</a></dd>" >> $(README_FILE)
-	echo "<dt>For all user accounts on the computer</dt>" >> $(README_FILE)
-	echo "<dd><a href=\"file:///%CommonProgramFiles%/\">%ProgramFiles%\Common Files\Pd-l2ork</a></dd>" >> $(README_FILE)
-endif
-	echo "</dl>" >> $(README_FILE)
-	echo "</p>" >> $(README_FILE)
-	echo "<h3>License</h3>" >> $(README_FILE)	
-	echo "<p>" >> $(README_FILE)
-	echo 'This package is released under the <a href="http://www.gnu.org/copyleft/gpl.html" target="gpl">GNU GPL</a>.  The Pd core and some other included code is available under a <a href="http://pure-data.cvs.sourceforge.net/pure-data/pd/LICENSE.txt">BSD license</a> from the Pd source code repository on SourceForge.' >> $(README_FILE)
-	echo "</p>" >> $(README_FILE)
-	echo "<h3>Patented Algorithms</h3>" >> $(README_FILE)
-	echo "<p>" >> $(README_FILE)
-	echo "This package may contain software that is covered by patents in certain countries, like the U.S. and Germany.  In order to use this software you must have the proper license.  Below is a list of the known software packages that are covered by patents in some countries:" >> $(README_FILE)
-	echo "</p>" >> $(README_FILE)
-	echo "<ul>" >> $(README_FILE)
-	echo '<li><a href="http://en.wikipedia.org/wiki/MP3" target="license">MP3 aka MPEG-1 Part 3 Layer 3</a></li>' >> $(README_FILE)
-	echo '<li><a href="http://en.wikipedia.org/wiki/MPEG-2" target="license">MPEG-2</a></li>' >> $(README_FILE)
-	echo '<li><a href="http://en.wikipedia.org/wiki/MPEG-4#Licensing" target="license">MPEG-4</a></li>' >> $(README_FILE)
-	echo "</ul>" >> $(README_FILE)
-	echo '<p>Please consider trying to get rid of software patents in your country: <a href="http://www.nosoftwarepatents.com" target="nsp">http://www.nosoftwarepatents.com</a></p>' >> $(README_FILE)
-	#echo "<h3>Pure Data CVS Developers</h3>" >> $(README_FILE)	
-# this may seem whack, but it generates the list of developers from the SourceForge site: (as of 11-13-2014 this 404s, so we disable it)
-	#curl 'http://sourceforge.net/project/memberlist.php?group_id=55736' | grep -A2 -e '<td>' | sed 's|\(href="\)|target="w" \1http://sourceforge.net|' >> $(README_FILE)
-	#echo "</p>" >> $(README_FILE)
-	#echo "<p>" >> $(README_FILE)
-	#echo "Many others not listed have contributed their time and effort, this is just a list of the current developers in the SourceForge project.  But really, every Pd user is a developer and is encouraged to contribute to the CVS repository." >> $(README_FILE)
-	#echo "</p>" >> $(README_FILE)
-	#echo "<h3>Included Versions</h3>" >> $(README_FILE)	
-	#echo "<p>These externals are all included from the Pd CVS repository:</p>" >> $(README_FILE)
-	#echo "<ul>" >> $(README_FILE)
-	#echo "<li>pure data: $(PD_VERSION) " >> $(README_FILE)
-	#echo "<li>cyclone: $(CYCLONE_VERSION)" >> $(README_FILE)
-	#echo "<li>gem: $(GEM_VERSION)" >> $(README_FILE)
-	#echo "<li>iemlib: `date +20%y.%m.%d`" >> $(README_FILE)
-	#echo "<li>maxlib: $(MAXLIB_VERSION)" >> $(README_FILE)
-	#echo "<li>osc: $(OSC_VERSION)" >> $(README_FILE)
-	#echo "<li>pmpd: $(PMPD_VERSION)" >> $(README_FILE)
-	#echo "<li>pd-abstractions: `date +20%y.%m.%d`" >> $(README_FILE)
-	#echo "<li>pd-doc: `date +20%y.%m.%d`" >> $(README_FILE)
-	#echo "<li>pd-externals: `date +20%y.%m.%d`" >> $(README_FILE)
-	#echo "<li>pddp: `date +20%y.%m.%d`" >> $(README_FILE)
-	#echo "<li>pdp: $(PDP_VERSION)" >> $(README_FILE)
-	#echo "<li>pidip: $(PIDIP_VERSION)" >> $(README_FILE)
-	#echo "<li>toxy: $(TOXY_VERSION)" >> $(README_FILE)
-	#echo "<li>unauthorized: `date +20%y.%m.%d`" >> $(README_FILE)
-	#echo "<li>zexy: $(ZEXY_VERSION)" >> $(README_FILE)
-	#echo "</ul>" >> $(README_FILE)
-	echo "(this package was built on `date`) <BR>" >> $(README_FILE)
-	echo "</body></html>" >> $(README_FILE)
+	rm -f $(README_FILE)
+	$(MAKE) -C gendoc ReadMe-$(osname).html version="$(PD_L2ORK_VERSION)" build_version="$(PD_BUILD_VERSION)"
+	cp gendoc/ReadMe-$(osname).html $(README_FILE)
 
 
 
@@ -410,6 +316,10 @@ abstractions_clean:
 	-$(MAKE) -C $(abstractions_src) $(DEST_PATHS) clean
 
 doc_clean:
+# These are precious, don't clean them! Otherwise pre-generated docs will be
+# removed before the build starts, and the build system may not have the
+# required tools installed to re-generate them.
+#	$(MAKE) -C gendoc clean
 
 externals_clean:
 	-$(MAKE) -C $(externals_src) $(DEST_PATHS) clean
@@ -422,7 +332,7 @@ clean: abstractions_clean doc_clean externals_clean pd_clean
 	echo "Complete clean finished."
 
 
-distclean: cruft_clean
+distclean: cruft_clean doc_clean
 	$(MAKE) -C $(abstractions_src) distclean
 	-$(MAKE) -C $(extensions_src) distclean
 	$(MAKE) -C $(externals_src) distclean
diff --git a/packages/gendoc/Makefile b/packages/gendoc/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..479b2e27d657aa2810d87e639f6b468bbed2eabd
--- /dev/null
+++ b/packages/gendoc/Makefile
@@ -0,0 +1,38 @@
+# These are just dummy values for testing purposes, the parent Makefile should
+# override them.
+version = 2.17.0
+build_version = 20220809-rev.35c9bcab
+
+targets = $(addprefix ReadMe-, Linux Darwin MINGW) \
+$(addprefix Welcome-, Linux Darwin MINGW)
+markdown = $(addsuffix .md, $(targets))
+html = $(addsuffix .html, $(targets))
+
+# Note: This requires special tools (python-markdown, awk).
+all: html
+
+markdown: $(markdown)
+html: $(html)
+
+ReadMe-%.md: osname = $(patsubst ReadMe-%.md,%,$@)
+ReadMe-%.md: ReadMe.md
+	awk -f gendoc.awk osname="$(osname)" version="$(version)" build_version="$(build_version)" < $< > $@
+
+ReadMe-%.html: osname = $(patsubst ReadMe-%.html,%,$@)
+ReadMe-%.html: ReadMe-%.md pandoc-template.html
+	python -m markdown $< > ReadMe-body.html
+	sed -e "s/@version@/$(version) ($(osname))/g" -e '/--stylesheet--/r gh-pandoc.css' -e '/--body--/r ReadMe-body.html' pandoc-template.html > $@
+	rm -f ReadMe-body.html
+
+Welcome-%.md: osname = $(patsubst Welcome-%.md,%,$@)
+Welcome-%.md: Welcome.md
+	awk -f gendoc.awk osname="$(osname)" version="$(version)" build_version="$(build_version)" < $< > $@
+
+Welcome-%.html: osname = $(patsubst Welcome-%.html,%,$@)
+Welcome-%.html: Welcome-%.md pandoc-template.html
+	python -m markdown $< > Welcome-body.html
+	sed -e "s/@version@/$(version) ($(osname))/g" -e '/--stylesheet--/r gh-pandoc.css' -e '/--body--/r Welcome-body.html' pandoc-template.html > $@
+	rm -f Welcome-body.html
+
+clean:
+	rm -f $(markdown) $(html)
diff --git a/packages/gendoc/ReadMe.md b/packages/gendoc/ReadMe.md
new file mode 100644
index 0000000000000000000000000000000000000000..958b77b29a6e4bff0befbba3818f16660290d026
--- /dev/null
+++ b/packages/gendoc/ReadMe.md
@@ -0,0 +1,112 @@
+# Purr Data @version@ @osname@ (@build-version@)
+
+Pd is a real-time, graphical programming language for media processing created by Miller S. Puckette. It provides an environment for audio analysis, synthesis, and processing, with a rich set of multimedia capabilities. You can get Pd for Linux, Windows, Mac OSX, and BSD.
+
+Purr Data was created by Jonathan Wilkes as a portable version of Ico Bukvic's Pd-l2ork, which in turn was based on Hans-Christoph Steiner's popular Pd-extended, a distribution of Pd which included a lot of externals. Purr Data is a modern successor of Pd-extended which features many enhancements, especially in the user interface which was rewritten from scratch using modern web technologies. It is available for Linux, Mac, and Windows.
+
+- If you're new to Purr Data, you may first want to read our little tutorial introduction "[Meet the Cat](https://agraef.github.io/purr-data-intro)".
+
+- More information about Purr Data can be found on the [GitHub mirror](https://agraef.github.io/purr-data/) maintained by Albert Gräf.
+
+- Jonathan Wilkes' source code repository is available on [GitLab](https://git.purrdata.net/jwilkes/purr-data); this is where you should go for submitting bug reports and pull requests.
+
+- Information about Ico Bukvic's Pd-l2ork version (which has been updated in 2021 and is now based on an earlier Purr Data version) can be found on the [Pd-l2ork website](https://l2ork.music.vt.edu/main/make-your-own-l2ork/software/).
+
+- General information about Pd is available at <https://puredata.info>.
+
+@linux@
+This is the @osname@ build of the Purr Data package.
+@linux@
+@darwin@
+This is the @osname@ (Mac OSX) build of the Purr Data package.
+@darwin@
+@mingw@
+This is the @osname@ (Windows) build of the Purr Data package.
+@mingw@
+Purr Data is available for a variety of different platforms, and you can also compile it from source if you have the necessary development tools. Please check the [wiki](https://github.com/agraef/purr-data/wiki/Installation) for detailed installation instructions.
+
+## Installation
+
+@linux@
+The [JGU Packages](https://build.opensuse.org/project/show/home:aggraef:purr-data-jgu) are a complete collection of Purr Data packages for Arch Linux, Fedora, and recent Debian, Raspbian and Ubuntu releases. They are maintained by Albert Gräf from the Johannes Gutenberg University (JGU) and hosted at the OBS (Open Build Service) by openSUSE. Installation instructions can be found in the [wiki](https://github.com/agraef/purr-data/wiki/Installation#linux).
+@linux@
+
+@darwin@
+The latest Mac packages are available as disk images on [GitHub](https://github.com/agraef/purr-data/releases). To install Purr Data, drag the Pd-l2ork.app bundle in the disk image into your /Applications folder, or to the shortcut in the disk image.
+
+If you want to use PDP on Mac OS X, you may have to install X11. For details see [How do I install Pd on MacOS X?](https://puredata.info/docs/faq/macosx)
+@darwin@
+
+@mingw@
+The latest Windows packages are available as Inno Setup installers on [GitHub](https://github.com/agraef/purr-data/releases). Double-click the installer and follow the instructions. If you have a prior Purr Data installation, the installer will prompt you to first remove it. If your existing installation is much older, it is always a good idea to do this, in order to prevent garbled installations which mix files and registry entries of both versions.
+
+[ASIO4ALL](https://www.asio4all.com/) is a cost-free [ASIO](https://en.wikipedia.org/wiki/Audio_Stream_Input/Output) audio driver. If you have it installed then you can enable it in Purr Data by choosing the **ASIO** option in the **Audio** tab of the Preferences dialog. Using ASIO4ALL will often give you lower latency and generally better audio performance.
+@mingw@
+
+## Usage
+
+@linux@
+If you installed Purr Data from the JGU repositories, then the executable will be named `purr-data`, and your desktop menus should contain an entry for `Purr-Data`. Use the former to launch Purr Data from the shell, and the latter to run the program from your desktop environment as usual.
+@linux@
+
+@darwin@
+After installation you will find `Pd-l2ork` in the Launchpad, which can be run by clicking on the icon as usual. Note that Purr Data is distributed as an application bundle on the Mac, but you can use the `open` command to launch it from the shell as follows: `open -a Pd-l2ork`
+@darwin@
+
+@mingw@
+After installation you will find an entry for `Purr-Data` in the start menu, which can be run by clicking on the icon as usual. If you opted to create a desktop and/or quick-launch icon during installation, you should be able to find these on your desktop as well.
+
+Purr Data can also be launched from the Windows command line. The executable is named `pd.com` and is located in the `%ProgramFiles%\Purr Data\bin` directory (`%ProgramFiles(x86)%\Purr Data\bin` if you installed the 32 bit version). For instance, using the command prompt, i.e., cmd.exe, you can launch the program as follows (the quotes are needed since the path contains spaces): `"%ProgramFiles%\Purr Data\bin\pd"`
+@mingw@
+
+## Installing Externals, Objects, and Help files
+
+If you would like to install other externals, objects, help files, etc., there are special folders that Purr Data uses, which are listed below. If the folder does not exist, you should create it. You can find out more details about this by reading this FAQ: [How do I install externals and help files?](https://puredata.info/docs/faq/how-do-i-install-externals-and-help-files)
+
+@linux@
+- Only for the current user account: ~/pd-l2ork-externals
+- For all user accounts on the computer: /usr/local/lib/pd-l2ork-externals
+@linux@
+
+@darwin@
+- Only for the current user account: ~/Library/Pd-l2ork
+- For all user accounts on the computer: /Library/Pd-l2ork
+@darwin@
+
+@mingw@
+- Only for the current user account (open in File Explorer): [%AppData%\\Pd-l2ork](file:///%AppData%)
+- For all user accounts on the computer (open in File Explorer): [%CommonProgramFiles%\\Pd-l2ork](file:///%CommonProgramFiles%)
+@mingw@
+
+## Configuration
+
+By default, most of the included libraries are loaded at startup. To change this, set your own preferences in the **Startup** tab of the Preferences dialog.
+
+@linux@
+On Linux, configuration data (user preferences, help index, completions) lives in ~/.purr-data. You can remove this directory (`rm -rf ~/.purr-data`) to reset Purr Data to its defaults. This will also reset the help index and completion data (they will be re-created automatically).
+@linux@
+
+@darwin@
+On the Mac, the user preferences live in ~/Library/Preferences/org.puredata.pd-l2ork.plist. You can remove that file (`rm ~/Library/Preferences/org.puredata.pd-l2ork.plist`) to reset Purr Data to the default preferences.
+
+Some auxiliary configuration data (help index, completions) can be found in ~/.purr-data. You can remove this directory (`rm -rf ~/.purr-data`) to reset the help index and completion data (they will be re-created automatically).
+@darwin@
+
+@mingw@
+On Windows, the user preferences live in the Windows registry. You *can* delete the `[HKEY_LOCAL_MACHINE\SOFTWARE\Purr-Data]` key and all its subkeys, but that will give you a completely "vanilla" setup with *no* preloaded libraries at all. Some people may even like that, in order to build their own library configuration. But the easiest way to reset the registry to some sane defaults which preloads most included libraries, is to reinstall the program.
+
+Some auxiliary configuration data (help index, completions) is stored in [%AppData%\\Purr-Data](file:///%AppData%/Purr-Data). You can delete those files to reset the help index and completion data (they will be re-created automatically).
+@mingw@
+
+## License
+
+This package is released under the [GNU GPL](https://www.gnu.org/copyleft/gpl.html). The Pd core and some other included code is available under a [BSD license](https://github.com/pure-data/pure-data/blob/master/LICENSE.txt) from the Pd source code repository on [GitHub](https://github.com/pure-data/pure-data).
+
+## Patented Algorithms
+
+This package may contain software that is covered by patents in certain countries, like the U.S. and Germany. In order to use this software you must have the proper license. Known software packages that are covered by patents in some countries are [MP3](https://en.wikipedia.org/wiki/MP3) (a.k.a. MPEG-1 Layer 3), [MPEG-2](https://en.wikipedia.org/wiki/MPEG-2), [MPEG-4](https://en.wikipedia.org/wiki/MPEG-4). (Note that many of the MPEG-related patents have now expired in most countries; please check the linked Wikipedia articles for details.)
+
+Please consider trying to get rid of software patents in your country:
+<https://www.nosoftwarepatents.com>
+
+This document was created @date@.
diff --git a/packages/gendoc/Welcome.md b/packages/gendoc/Welcome.md
new file mode 100644
index 0000000000000000000000000000000000000000..e2209250b97dd861274acdef8a8856424c0eb4e4
--- /dev/null
+++ b/packages/gendoc/Welcome.md
@@ -0,0 +1,5 @@
+# Purr Data @version@ @osname@ (@build-version@)
+
+Purr Data was created by Jonathan Wilkes as a portable version of Ico Bukvic's Pd-l2ork. Pd-l2ork is a fork of Hans-Christoph Steiner's Pd-extended, which in turn is based on Miller S. Puckette's Pd. The included Pd abstractions and externals are the work of many people whose contributions are gratefully acknowledged.
+
+ACKNOWLEDGEMENTS. Thanks to Harry Castle, Krzysztof Czaja, Mark Danks, Christian Feldbauer, Guenter Geiger, Kerry Hagan, Trevor Johnson, Fernando Lopez-Lezcano, Adam Lindsay, Karl MacMillan, Thomas Musil, Toshinori Ohkouchi, Winfried Ritsch, Vibeke Sorensen, Rand Steiger, Hans-Christoph Steiner, Shahrokh Yadegari, David Zicarelli, Iohannes Zmoelnig, and probably many others for contributions of code, documentation, ideas, and expertise. This work has received generous support from the Intel Research Council.
diff --git a/packages/gendoc/gendoc.awk b/packages/gendoc/gendoc.awk
new file mode 100755
index 0000000000000000000000000000000000000000..17b950dfa84ea4ff90cb2f84e14eabc931bf5333
--- /dev/null
+++ b/packages/gendoc/gendoc.awk
@@ -0,0 +1,76 @@
+#! /usr/bin/awk -f
+
+# This is to be invoked with osname set to the OS identifier as returned by
+# $(uname -s) on the target system, i.e., "Linux" on Linux, "Darwin" on the
+# Mac, etc. Only the sections marked with the corresponding id (@linux@,
+# @darwin@, and @mingw@) will be included. In addition, @version@ and
+# @build-version@ will be replaced with the contents of the (string) variables
+# version and build_version, respectively, if specified on the command line.
+
+BEGIN {
+    # Default for osname if not set.
+    if (!osname) { "uname -s" | getline osname };
+    # Grab the current date, so that we can substitute it.
+    "date -u" | getline date
+}
+
+/^@mingw@$/ {
+    keep = osname ~ /^MINGW/;
+    init = !init;
+    skip = init && !keep;
+    skipped = !init && !keep;
+    next
+}
+/^@!mingw@$/ {
+    keep = osname ~ !/^MINGW/;
+    init = !init;
+    skip = init && !keep;
+    skipped = !init && !keep;
+    next
+}
+/^@linux@$/ {
+    keep = osname == "Linux";
+    init = !init;
+    skip = init && !keep;
+    skipped = !init && !keep;
+    next
+}
+/^@!linux@$/ {
+    keep = osname != "Linux";
+    init = !init;
+    skip = init && !keep;
+    skipped = !init && !keep;
+    next
+}
+/^@darwin@$/ {
+    keep = osname == "Darwin";
+    init = !init;
+    skip = init && !keep;
+    skipped = !init && !keep;
+    next
+}
+/^@!darwin@$/ {
+    keep = osname != "Darwin";
+    init = !init;
+    skip = init && !keep;
+    skipped = !init && !keep;
+    next
+}
+
+skip { next }
+# Get rid of extra empty lines after a skipped section.
+skipped && /^[[:space:]]*$/ { skipped = 0; next }
+
+!skip {
+    skipped = 0;
+    line = $0;
+    gsub(/@date@/, date, line)
+    gsub(/@osname@/, osname, line)
+    if (version) {
+        gsub(/@version@/, version, line)
+    }
+    if (build_version) {
+        gsub(/@build-version@/, build_version, line)
+    }
+    print(line)
+}
diff --git a/packages/gendoc/gh-pandoc.css b/packages/gendoc/gh-pandoc.css
new file mode 100644
index 0000000000000000000000000000000000000000..1da4466b0067b171a0cee83be4d3ec8f87f41e90
--- /dev/null
+++ b/packages/gendoc/gh-pandoc.css
@@ -0,0 +1,801 @@
+/*! normalize.css v3.0.1 | MIT License | git.io/normalize */
+
+/**
+* 1. Set default font family to sans-serif.
+* 2. Prevent iOS text size adjust after orientation change, without disabling
+*    user zoom.
+*/
+
+html {
+  font-family: sans-serif; /* 1 */
+  -ms-text-size-adjust: 100%; /* 2 */
+  -webkit-text-size-adjust: 100%; /* 2 */
+}
+
+/**
+* Remove default margin.
+*/
+
+body {
+  margin: 0;
+}
+
+/* HTML5 display definitions
+========================================================================== */
+
+/**
+* Correct `block` display not defined for any HTML5 element in IE 8/9.
+* Correct `block` display not defined for `details` or `summary` in IE 10/11 and Firefox.
+* Correct `block` display not defined for `main` in IE 11.
+*/
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+nav,
+section,
+summary {
+  display: block;
+}
+
+/**
+* 1. Correct `inline-block` display not defined in IE 8/9.
+* 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
+*/
+
+audio,
+canvas,
+progress,
+video {
+  display: inline-block; /* 1 */
+  vertical-align: baseline; /* 2 */
+}
+
+/**
+* Prevent modern browsers from displaying `audio` without controls.
+* Remove excess height in iOS 5 devices.
+*/
+
+audio:not([controls]) {
+  display: none;
+  height: 0;
+}
+
+/**
+* Address `[hidden]` styling not present in IE 8/9/10.
+* Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
+*/
+
+[hidden],
+template {
+  display: none;
+}
+
+/* Links
+========================================================================== */
+
+/**
+* Remove the gray background color from active links in IE 10.
+*/
+
+a {
+  background: transparent;
+}
+
+/**
+* Improve readability when focused and also mouse hovered in all browsers.
+*/
+
+a:active,
+a:hover {
+  outline: 0;
+}
+
+/* Text-level semantics
+========================================================================== */
+
+/**
+* Address styling not present in IE 8/9/10/11, Safari, and Chrome.
+*/
+
+abbr[title] {
+  border-bottom: 1px dotted;
+}
+
+/**
+* Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
+*/
+
+b,
+strong {
+  font-weight: bold;
+}
+
+/**
+* Address styling not present in Safari and Chrome.
+*/
+
+dfn {
+  font-style: italic;
+}
+
+/**
+* Address variable `h1` font-size and margin within `section` and `article`
+* contexts in Firefox 4+, Safari, and Chrome.
+*/
+
+h1 {
+  font-size: 2em;
+  margin: 0.67em 0;
+}
+
+/**
+* Address styling not present in IE 8/9.
+*/
+
+mark {
+  background: #ff0;
+  color: #000;
+}
+
+/**
+* Address inconsistent and variable font size in all browsers.
+*/
+
+small {
+  font-size: 80%;
+}
+
+/**
+* Prevent `sub` and `sup` affecting `line-height` in all browsers.
+*/
+
+sub,
+sup {
+  font-size: 75%;
+  line-height: 0;
+  position: relative;
+  vertical-align: baseline;
+}
+
+sup {
+  top: -0.5em;
+}
+
+sub {
+  bottom: -0.25em;
+}
+
+/* Embedded content
+========================================================================== */
+
+/**
+* Remove border when inside `a` element in IE 8/9/10.
+*/
+
+img {
+  border: 0;
+}
+
+/**
+* Correct overflow not hidden in IE 9/10/11.
+*/
+
+svg:not(:root) {
+  overflow: hidden;
+}
+
+/* Grouping content
+========================================================================== */
+
+/**
+* Address margin not present in IE 8/9 and Safari.
+*/
+
+figure {
+  margin: 1em 40px;
+}
+
+/**
+* Address differences between Firefox and other browsers.
+*/
+
+hr {
+  -moz-box-sizing: content-box;
+  box-sizing: content-box;
+  height: 0;
+}
+
+/**
+* Contain overflow in all browsers.
+*/
+
+pre {
+  overflow: auto;
+}
+
+/**
+* Address odd `em`-unit font size rendering in all browsers.
+*/
+
+code,
+kbd,
+pre,
+samp {
+  font-family: monospace, monospace;
+  font-size: 1em;
+}
+
+/* Forms
+========================================================================== */
+
+/**
+* Known limitation: by default, Chrome and Safari on OS X allow very limited
+* styling of `select`, unless a `border` property is set.
+*/
+
+/**
+* 1. Correct color not being inherited.
+*    Known issue: affects color of disabled elements.
+* 2. Correct font properties not being inherited.
+* 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
+*/
+
+button,
+input,
+optgroup,
+select,
+textarea {
+  color: inherit; /* 1 */
+  font: inherit; /* 2 */
+  margin: 0; /* 3 */
+}
+
+/**
+* Address `overflow` set to `hidden` in IE 8/9/10/11.
+*/
+
+button {
+  overflow: visible;
+}
+
+/**
+* Address inconsistent `text-transform` inheritance for `button` and `select`.
+* All other form control elements do not inherit `text-transform` values.
+* Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
+* Correct `select` style inheritance in Firefox.
+*/
+
+button,
+select {
+  text-transform: none;
+}
+
+/**
+* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
+*    and `video` controls.
+* 2. Correct inability to style clickable `input` types in iOS.
+* 3. Improve usability and consistency of cursor style between image-type
+*    `input` and others.
+*/
+
+button,
+html input[type="button"], /* 1 */
+input[type="reset"],
+input[type="submit"] {
+  -webkit-appearance: button; /* 2 */
+  cursor: pointer; /* 3 */
+}
+
+/**
+* Re-set default cursor for disabled elements.
+*/
+
+button[disabled],
+html input[disabled] {
+  cursor: default;
+}
+
+/**
+* Remove inner padding and border in Firefox 4+.
+*/
+
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+  border: 0;
+  padding: 0;
+}
+
+/**
+* Address Firefox 4+ setting `line-height` on `input` using `!important` in
+* the UA stylesheet.
+*/
+
+input {
+  line-height: normal;
+}
+
+/**
+* It's recommended that you don't attempt to style these elements.
+* Firefox's implementation doesn't respect box-sizing, padding, or width.
+*
+* 1. Address box sizing set to `content-box` in IE 8/9/10.
+* 2. Remove excess padding in IE 8/9/10.
+*/
+
+input[type="checkbox"],
+input[type="radio"] {
+  box-sizing: border-box; /* 1 */
+  padding: 0; /* 2 */
+}
+
+/**
+* Fix the cursor style for Chrome's increment/decrement buttons. For certain
+* `font-size` values of the `input`, it causes the cursor style of the
+* decrement button to change from `default` to `text`.
+*/
+
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+  height: auto;
+}
+
+/**
+* 1. Address `appearance` set to `searchfield` in Safari and Chrome.
+* 2. Address `box-sizing` set to `border-box` in Safari and Chrome
+*    (include `-moz` to future-proof).
+*/
+
+input[type="search"] {
+  -webkit-appearance: textfield; /* 1 */
+  -moz-box-sizing: content-box;
+  -webkit-box-sizing: content-box; /* 2 */
+  box-sizing: content-box;
+}
+
+/**
+* Remove inner padding and search cancel button in Safari and Chrome on OS X.
+* Safari (but not Chrome) clips the cancel button when the search input has
+* padding (and `textfield` appearance).
+*/
+
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+  -webkit-appearance: none;
+}
+
+/**
+* Define consistent border, margin, and padding.
+*/
+
+fieldset {
+  border: 1px solid #c0c0c0;
+  margin: 0 2px;
+  padding: 0.35em 0.625em 0.75em;
+}
+
+/**
+* 1. Correct `color` not being inherited in IE 8/9/10/11.
+* 2. Remove padding so people aren't caught out if they zero out fieldsets.
+*/
+
+legend {
+  border: 0; /* 1 */
+  padding: 0; /* 2 */
+}
+
+/**
+* Remove default vertical scrollbar in IE 8/9/10/11.
+*/
+
+textarea {
+  overflow: auto;
+}
+
+/**
+* Don't inherit the `font-weight` (applied by a rule above).
+* NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
+*/
+
+optgroup {
+  font-weight: bold;
+}
+
+/* Tables
+========================================================================== */
+
+/**
+* Remove most spacing between table cells.
+*/
+
+table {
+  border-collapse: collapse;
+  border-spacing: 0;
+}
+
+td,
+th {
+  padding: 0;
+}
+
+/* Figure captions */
+
+.caption {
+  margin-bottom: 5em;
+}
+
+/*! End of normalize.css
+========================================================================== */
+
+/* Github styles
+========================================================================== */
+
+* {
+  box-sizing: border-box;
+}
+body {
+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
+  font-size: 12pt;
+  line-height: 1.6;
+  margin: auto;
+  max-width: 920px;
+  min-width: 360px;
+  padding: 2rem;
+  word-wrap: break-word;
+}
+
+/* Headers
+========================================================================== */
+
+h1, h2, h3, h4, h5, h6 {
+  font-weight: 600;
+  line-height: 1.25;
+  margin-bottom: 16px;
+  margin-top: 24px;
+}
+h1 {
+  padding-bottom: 0.3em;
+  font-size: 2em;
+  border-bottom: 1px solid #eee;
+}
+h2 {
+  padding-bottom: 0.3em;
+  font-size: 1.5em;
+  border-bottom: 1px solid #eee;
+}
+h3 {
+  font-size: 1.25em;;
+}
+h4 {
+  font-size: 1em;
+}
+h5 {
+  font-size: 0.875em;
+}
+h6 {
+  font-size: 0.85em;
+  color: #777;
+}
+h1 tt, h1 code,
+h2 tt, h2 code,
+h3 tt, h3 code,
+h4 tt, h4 code,
+h5 tt, h5 code,
+h6 tt, h6 code {
+  font-size: inherit;
+}
+body > h2:first-child {
+  margin-top: 0;
+  padding-top: 0;
+}
+body > h1:first-child {
+  margin-top: 0;
+  padding-top: 0;
+}
+body > h1:first-child+h2 {
+  margin-top: 0;
+  padding-top: 0;
+}
+body > h3:first-child,
+body > h4:first-child,
+body > h5:first-child,
+body > h6:first-child {
+  margin-top: 0;
+  padding-top: 0;
+}
+a:first-child h1,
+a:first-child h2,
+a:first-child h3,
+a:first-child h4,
+a:first-child h5,
+a:first-child h6 {
+  margin-top: 0;
+  padding-top: 0;
+}
+
+/* Flow Content
+========================================================================== */
+
+a {
+  color: #4078c0;
+  text-decoration: none;
+}
+a:active, a:hover {
+  outline: 0;
+  text-decoration: underline;
+}
+sup, sub, a.footnote {
+  font-size: 75%;
+  line-height: 0;
+  position: relative;
+  vertical-align: baseline;
+}
+sub {
+  bottom: -0.25em;
+}
+sup {
+  top: -0.5em;
+}
+
+/* Block Content
+========================================================================== */
+
+ol, ul {
+  margin-bottom: 16px;
+  margin-top: 0;
+  padding-left: 2em;
+}
+p, blockquote, table, pre {
+  margin: 15px 0;
+}
+ul, ol {
+  padding-left: 2em;
+}
+ul.no-list, ol.no-list {
+  padding: 0;
+  list-style-type: none;
+}
+ul ul, ul ol, ol ol, ol ul {
+  margin-top: 0;
+  margin-bottom: 0;
+}
+li > p {
+  margin-top: 16px;
+}
+li + li {
+  margin-top: 0.25em;;
+}
+ol li ul:first-of-type {
+  margin-top: 0;
+}
+hr {
+  background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAECAYAAACtBE5DAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OENDRjNBN0E2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OENDRjNBN0I2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4Q0NGM0E3ODY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4Q0NGM0E3OTY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PqqezsUAAAAfSURBVHjaYmRABcYwBiM2QSA4y4hNEKYDQxAEAAIMAHNGAzhkPOlYAAAAAElFTkSuQmCC) repeat-x 0 0;
+  border: 0 none;
+  color: #ccc;
+  height: 4px;
+  margin: 16px 0;
+  padding: 0;
+}
+h1 + p,
+h2 + p,
+h3 + p,
+h4 + p,
+h5 + p,
+h6 + p,
+ul li > :first-child,
+ol li > :first-child {
+  margin-top: 0;
+}
+dl {
+  padding: 0;
+}
+dl dt {
+  font-size: 1em;
+  font-weight: bold;
+  font-style: italic;
+  padding: 0;
+  margin: 15px 0 5px;
+}
+dl dt:first-child {
+  padding: 0;
+}
+dl dt > :first-child {
+  margin-top: 0;
+}
+dl dt > :last-child {
+  margin-bottom: 0;
+}
+dl dd {
+  margin: 0 0 15px;
+  padding: 0 15px;
+}
+dl dd > :first-child {
+  margin-top: 0;
+}
+dl dd > :last-child {
+  margin-bottom: 0;
+}
+blockquote {
+  border-left: 4px solid #DDD;
+  padding: 0 15px;
+  color: #777;
+}
+blockquote > :first-child {
+  margin-top: 0;
+}
+blockquote > :last-child {
+  margin-bottom: 0;
+}
+table {
+  border-collapse: collapse;
+  border-spacing: 0;
+  font-size: 100%;
+  font: inherit;
+}
+table th {
+  font-weight: bold;
+  border: 1px solid #ccc;
+  padding: 6px 13px;
+}
+table td {
+  border: 1px solid #ccc;
+  padding: 6px 13px;
+}
+table td > p:first-child {
+  margin-top: 0;
+}
+table td > p:last-child {
+  margin-bottom: 0;
+}
+table tr {
+  border-top: 1px solid #ccc;
+  background-color: #fff;
+}
+table tr:nth-child(2n) {
+  background-color: #f8f8f8;
+}
+img {
+  max-width: 100%;
+}
+
+/* Code
+========================================================================== */
+
+code, tt {
+  padding: 0;
+  padding-top: 0.2em;
+  padding-bottom: 0.2em;
+  margin: 0;
+  font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
+  font-size: 10pt;
+  background-color: rgba(0, 0, 0, 0.04);
+  border-radius: 3px;
+}
+pre > code {
+  margin: 0;
+  padding: 0;
+  white-space: pre;
+  border: 0;
+  background: transparent;
+}
+pre {
+  padding: 16px;
+  margin-top: 0;
+  margin-bottom: 0;
+  background-color: #f8f8f8;
+  font-size: 10pt;
+  line-height: 19px;
+  overflow: auto;
+  border-radius: 3px;
+}
+pre code, pre tt {
+  background-color: transparent;
+  border: 0;
+}
+code::before, code::after,
+tt::before, tt::after {
+  letter-spacing: -0.2em;
+	content: "\00a0";
+}
+pre code::before, pre code::after, pre tt::before, pre tt::after {
+	content: normal;
+}
+code > span.kw { color: #a71d5d; font-weight: normal; } /* Keyword */
+code > span.dt { color: inherit; } /* DataType */
+code > span.dv { color: #0086b3; } /* DecVal */
+code > span.bn { color: #0086b3; } /* BaseN */
+code > span.fl { color: #0086b3; } /* Float */
+code > span.ch { color: #183691; } /* Char */
+code > span.st { color: #183691; } /* String */
+code > span.co { color: #969896; font-style: normal; } /* Comment */
+code > span.ot { color: #a71d5d; } /* Other */
+code > span.al { color: #ff0000; } /* Alert */
+code > span.fu { color: #795da3; } /* Function */
+code > span.er { color: #ff0000; font-weight: bold; } /* Error */
+code > span.wa { color: #969896; font-weight: bold; font-style: italic; } /* Warning */
+code > span.cn { color: #880000; } /* Constant */
+code > span.sc { color: #183691; } /* SpecialChar */
+code > span.vs { color: #183691; } /* VerbatimString */
+code > span.ss { color: #bb6688; } /* SpecialString */
+code > span.im { } /* Import */
+code > span.va { color: #19177c; } /* Variable */
+code > span.cf { color: #a71d5d; font-weight: normal; } /* ControlFlow */
+code > span.op { color: #666666; } /* Operator */
+code > span.bu { } /* BuiltIn */
+code > span.ex { } /* Extension */
+code > span.pp { color: #bc7a00; } /* Preprocessor */
+code > span.at { color: #0086b3; } /* Attribute */
+code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
+code > span.an { color: #969896; font-weight: bold; font-style: italic; } /* Annotation */
+code > span.cv { color: #969896; font-weight: bold; font-style: italic; } /* CommentVar */
+code > span.in { color: #969896; font-weight: bold; font-style: italic; } /* Information */
+
+/* Print
+========================================================================== */
+
+@media print {
+  body {
+    background: #fff;
+  }
+  img, pre, blockquote, table, figure {
+    page-break-inside: avoid;
+  }
+  body {
+    background: #fff;
+    border: 0;
+  }
+  code {
+    background-color: #fff;
+    color: #333!important;
+    padding: 0 .2em;
+    border: 1px solid #dedede;
+  }
+  pre {
+    background: #fff;
+  }
+  pre code {
+    background-color: white!important;
+    overflow: visible;
+  }
+}
+
+/* Selection
+========================================================================== */
+
+@media screen {
+  ::selection {
+    background: rgba(157, 193, 200, 0.5);
+  }
+  h1::selection {
+    background-color: rgba(45, 156, 208, 0.3);
+  }
+  h2::selection {
+    background-color: rgba(90, 182, 224, 0.3);
+  }
+  h3::selection, h4::selection, h5::selection, h6::selection, li::selection, ol::selection {
+    background-color: rgba(133, 201, 232, 0.3);
+  }
+  code::selection {
+    background-color: rgba(0, 0, 0, 0.7);
+    color: #eee;
+  }
+  code span::selection {
+    background-color: rgba(0, 0, 0, 0.7)!important;
+    color: #eee!important;
+  }
+  a::selection {
+    background-color: rgba(255, 230, 102, 0.2);
+  }
+  .inverted a::selection {
+    background-color: rgba(255, 230, 102, 0.6);
+  }
+  td::selection, th::selection, caption::selection {
+    background-color: rgba(180, 237, 95, 0.5);
+  }
+}
\ No newline at end of file
diff --git a/packages/gendoc/pandoc-template.html b/packages/gendoc/pandoc-template.html
new file mode 100644
index 0000000000000000000000000000000000000000..520f57d9dbce5d013db98ddb4e27b486ec7ccec3
--- /dev/null
+++ b/packages/gendoc/pandoc-template.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" lang xml:lang>
+<head>
+  <meta charset="utf-8" />
+  <meta name="generator" content="pandoc" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
+  <title>Purr Data @version@</title>
+  <style>
+    code{white-space: pre-wrap;}
+    span.smallcaps{font-variant: small-caps;}
+    span.underline{text-decoration: underline;}
+    div.column{display: inline-block; vertical-align: top; width: 50%;}
+    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
+    ul.task-list{list-style: none;}
+    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
+  </style>
+  <style type="text/css">
+<!--stylesheet-->
+</style>
+  <!--[if lt IE 9]>
+    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
+  <![endif]-->
+</head>
+<body>
+<!--body-->
+</body>
+</html>