rmd_reader.py 4.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #-*- conding: utf-8 -*-
  2. import os
  3. import warnings
  4. import logging
  5. logger = logging.getLogger('RMD_READER')
  6. from pelican import readers
  7. from pelican import signals
  8. from pelican import settings
  9. knitr = None
  10. rmd = False
  11. fig_path = None
  12. def initsignal(pelicanobj):
  13. global knitr, rmd, fig_path, robjects
  14. try:
  15. with warnings.catch_warnings():
  16. warnings.simplefilter("ignore")
  17. from rpy2.robjects.packages import importr
  18. import rpy2.robjects as robjects
  19. knitr = importr('knitr')
  20. idx = knitr.opts_knit.names.index('set')
  21. PATH = pelicanobj.settings.get('PATH','%s/content' % settings.DEFAULT_CONFIG.get('PATH'))
  22. logger.debug("RMD_READER PATH = %s", PATH)
  23. knitr.opts_knit[idx](**{'base.dir': PATH})
  24. knitroptsknit = pelicanobj.settings.get('RMD_READER_KNITR_OPTS_KNIT', None)
  25. if knitroptsknit:
  26. knitr.opts_knit[idx](**{str(k): v for k,v in knitroptsknit.items()})
  27. idx = knitr.opts_chunk.names.index('set')
  28. knitroptschunk = pelicanobj.settings.get('RMD_READER_KNITR_OPTS_CHUNK', None)
  29. if knitroptschunk:
  30. fig_path = knitroptschunk['fig.path'] if knitroptschunk.has_key('fig.path') else 'figure/'
  31. knitr.opts_chunk[idx](**{str(k): v for k,v in knitroptschunk.items()})
  32. rmd = True
  33. except ImportError as ex:
  34. rmd = False
  35. class RmdReader(readers.BaseReader):
  36. file_extensions = ['Rmd', 'rmd']
  37. @property
  38. def enabled():
  39. return rmd
  40. # You need to have a read method, which takes a filename and returns
  41. # some content and the associated metadata.
  42. def read(self, filename):
  43. """Parse content and metadata of markdown files"""
  44. QUIET = self.settings.get('RMD_READER_KNITR_QUIET', True)
  45. ENCODING = self.settings.get('RMD_READER_KNITR_ENCODING', 'UTF-8')
  46. CLEANUP = self.settings.get('RMD_READER_CLEANUP', True)
  47. RENAME_PLOT = self.settings.get('RMD_READER_RENAME_PLOT', 'chunklabel')
  48. logger.debug("RMD_READER_KNITR_QUIET = %s", QUIET)
  49. logger.debug("RMD_READER_KNITR_ENCODING = %s", ENCODING)
  50. logger.debug("RMD_READER_CLEANUP = %s", CLEANUP)
  51. logger.debug("RMD_READER_RENAME_PLOT = %s", RENAME_PLOT)
  52. # replace single backslashes with double backslashes
  53. filename = filename.replace('\\', '\\\\')
  54. # parse Rmd file - generate md file
  55. md_filename = filename.replace('.Rmd', '.aux').replace('.rmd', '.aux')
  56. if RENAME_PLOT == 'chunklabel' or RENAME_PLOT == 'directory':
  57. if RENAME_PLOT == 'chunklabel':
  58. chunk_label = os.path.splitext(os.path.basename(filename))[0]
  59. logger.debug('Chunk label: %s', chunk_label)
  60. elif RENAME_PLOT == 'directory':
  61. chunk_label = 'unnamed_chunk'
  62. PATH = self.settings.get('PATH','%s/content' % settings.DEFAULT_CONFIG.get('PATH'))
  63. src_name = os.path.splitext(os.path.relpath(filename, PATH))[0]
  64. idx = knitr.opts_chunk.names.index('set')
  65. knitroptschunk = { 'fig.path': os.path.join(fig_path, src_name) }
  66. knitr.opts_chunk[idx](**{str(k): v for k,v in knitroptschunk.items()})
  67. logger.debug('Figures path: %s, chunk label: %s', knitroptschunk['fig.path'], chunk_label)
  68. robjects.r('''
  69. opts_knit$set(unnamed.chunk.label="{unnamed_chunk_label}")
  70. render_markdown()
  71. hook_plot <- knit_hooks$get('plot')
  72. knit_hooks$set(plot=function(x, options) hook_plot(paste0("{{filename}}/", x), options))
  73. '''.format(unnamed_chunk_label=chunk_label))
  74. knitr.knit(filename, md_filename, quiet=QUIET, encoding=ENCODING)
  75. # read md file - create a MarkdownReader
  76. md_reader = readers.MarkdownReader(self.settings)
  77. content, metadata = md_reader.read(md_filename)
  78. # remove md file
  79. if CLEANUP:
  80. os.remove(md_filename)
  81. return content, metadata
  82. def add_reader(readers):
  83. readers.reader_classes['rmd'] = RmdReader
  84. def register():
  85. signals.readers_init.connect(add_reader)
  86. signals.initialized.connect(initsignal)