Browse Source

Add TextBundle plugin

Thanks to the authors of the [rmd_reader
plugin](https://github.com/getpelican/pelican-plugins/tree/master/rmd_reader)
for the code to bootstrap this plugin!
Dirk Rüdiger 10 years ago
parent
commit
23c9592d93
4 changed files with 182 additions and 0 deletions
  1. 30 0
      Readme.md
  2. 1 0
      __init__.py
  3. 81 0
      migrate.sh
  4. 70 0
      textbundle.py

+ 30 - 0
Readme.md

@@ -0,0 +1,30 @@
+# Textbundle Reader
+
+This plugin helps you creating posts from Textbundles
+(http://textbundle.org/spec/).
+
+In anutshell a textbundle is a folder with a ".textbundle" name suffix and
+a predefined folder hierarchy. The Markdown text is always in a file "text.md",
+all referenced assets (images, videos, etc.) are located in a subfolder named
+"assets/" and a file "info.json" (obviously in JSON format) provides some meta
+data.
+
+## Dependency
+
+This plugin needs [Markdown](https://pypi.python.org/pypi/Markdown) to work.
+Install it with:
+
+```
+pip install Markdown
+```
+
+## Usage
+
+Install the textbundle plugin and add it to the PLUGINS setting:
+
+```
+PLUGINS = [
+    'textbundle',
+    ...
+    ]
+```

+ 1 - 0
__init__.py

@@ -0,0 +1 @@
+from .textbundle import *

+ 81 - 0
migrate.sh

@@ -0,0 +1,81 @@
+#!/bin/sh
+
+PAGE_PATH="content/pages"
+ARTICLE_PATH="content/posts"
+IMAGE_PATH="content/images"
+FILE_PATH="content/files"
+
+IMAGE_URL="/images/"
+FILE_URL="/files/"
+
+# Set to "1" if all files should be converted.
+# Otherwise only files containing image links are converted.
+CONVERT_ALL_FILES=0
+
+MKDIR="mkdir -p"
+MV="git mv"
+SED="sed"
+## All modifying commands can be switched to DRY-mode by uncommenting te following lines
+#MKDIR="echo mkdir -p"
+#MV="echo git mv"
+#SED="echo sed"
+
+rename_markdown_files() {
+  for md_file in $PAGE_PATH/*.md $ARTICLE_PATH/*.md
+  do
+    [ -e "$md_file" ] || continue
+    tb_file="${md_file/.md/.textbundle}"
+    grep -qE '\!\[.*\]\([^ \)]*' "$md_file" /dev/null
+    if [ $? == 0 -o $CONVERT_ALL_FILES ]
+    then
+      echo "Convert '$md_file'"
+      $MKDIR "$tb_file/assets"
+      $MV "$md_file" "$tb_file/text.md"
+    else
+      echo "Skip '$md_file', because it doesn't contain image links."
+    fi
+  done
+}
+
+create_metadata() {
+  for tb_file in $PAGE_PATH/*.textbundle $ARTICLE_PATH/*.textbundle
+  do
+    test -e "$tb_file/info.json" || cat > "$tb_file/info.json" <<INFOJSON
+{
+  "version":              1,
+  "transient":            false,
+  "creatorURL":           "http://getpelican.com/",
+  "creatorIdentifier":    "https://github.com/DirkR/pelican-textbundle"
+}
+INFOJSON
+  done
+}
+
+move_assets() {
+  echo '# Apache Rewrite rules for moved assets' > assets_htaccess_fragment.txt
+  for tb_file in $PAGE_PATH/*.textbundle $ARTICLE_PATH/*.textbundle
+  do
+    md_file="$tb_file/text.md"
+    [ -e "$md_file" ] || continue
+    for asset in $(perl -n -e '/\[.*\]\((\/[^ \)]*)/ && print "$1\n"' "$md_file")
+    do
+      if [ -z "${asset##*$IMAGE_URL*}" -o -z "${asset##*$FILE_URL*}" ]
+      then
+        rel_path=$(echo $asset | $SED -e "s!^($IMAGE_URL|$FILE_URL)!!")
+        asset_name=$(basename $asset)
+        [ -d "$tb_file/assets" ] || MKDIR "$tb_file/assets"
+        $MV "content$asset" "$tb_file/assets/$asset_name"
+        slug=$(perl -n -e '/slug\s*:\s*(.+)/ && print $1' "$tb_file/text.md")
+        if [ ! -z "$slug" ]
+        then
+          echo "RewriteRule ^$asset /post/$slug/assets/$asset_name [R=301,L]" >> assets_htaccess_fragment.txt
+        fi
+        $SED -i.bak -e "s|$asset|assets/$asset_name|g" "$md_file"
+      fi
+    done
+  done
+}
+
+rename_markdown_files
+create_metadata
+move_assets

+ 70 - 0
textbundle.py

@@ -0,0 +1,70 @@
+#-*- conding: utf-8 -*-
+
+import os
+import logging
+import shutil
+from glob import glob
+
+from pelican import readers
+from pelican import signals
+#from pelican.utils import pelican_open
+from markdown import Markdown
+
+logger = logging.getLogger(__name__)
+
+
+class TextbundleReader(readers.MarkdownReader):
+    enabled = Markdown
+    path_mappings = {}
+    file_extensions = ['textbundle']
+
+    # You need to have a read method, which takes a filename and returns
+    # some content and the associated metadata.
+    def read(self, filename):
+        md_filename = "{}/text.md".format(filename)
+        logger.debug('Found textbundle {}'.format(filename))
+        return super(TextbundleReader, self).read(md_filename)
+
+
+def add_reader(readers):
+    readers.reader_classes['textbundle'] = TextbundleReader
+
+
+def copy_article_assets(generator):
+    logging.debug('Copy Article textbundle assets')
+    inspect_content_items(generator.articles, generator.output_path)
+
+
+def copy_page_assets(generator):
+    logging.debug('Copy Page textbundle assets')
+    inspect_content_items(generator.pages, generator.output_path)
+
+
+def inspect_content_items(content_items, output_path):
+    for item in content_items:
+        foldername = os.path.join(
+            output_path,
+            os.path.dirname(item.save_as),
+            'assets'
+        )
+        assets = glob("{}/assets/*.*".format(os.path.dirname(item.source_path)))
+        if len(assets) > 0:
+            copy_assets_to_outputfolder(assets, foldername)
+
+
+def copy_assets_to_outputfolder(assets, foldername):
+    if not os.path.exists(foldername):
+        os.makedirs(foldername)
+    for asset in assets:
+        asset_path = os.path.join(foldername, os.path.basename(asset))
+        if not os.path.exists(asset_path):
+            logger.debug('copying asset {} to {}'.format(asset, foldername))
+            shutil.copy2(asset, asset_path)
+        else:
+            logger.debug('skipping existing asset {}'.format(foldername))
+
+
+def register():
+    signals.readers_init.connect(add_reader)
+    signals.article_generator_finalized.connect(copy_article_assets)
+    signals.page_generator_finalized.connect(copy_page_assets)