Esempio n. 1
0
 def _update_config(self):
     self.config = deepcopy(self.defaults)
     
     logger.debug('>> Searching for config')
     
     for ext in ('.yml', '.yaml'):
         f = File(normpath(self.src.path, 'config' + ext))
         
         if f.exists:
             logger.debug('..  found: %s', f.path)
             
             try:
                 self.config.update(Config(f.content))
             except ConfigException as e:
                 raise ConfigException(e.message, 'src: {0}'.format(f.path))
             
             self.config['locale'] = self.opts.get('locale', self.config['locale'])
             
             self.config['assets_url'] = absurl(self.config['assets_url'], '')
             self.config['base_url'] = absurl(self.opts.get('base_url', self.config['base_url']), '')
             
             for setting in ('archives_url', 'posts_url', 'tags_url'):
                 self.config[setting] = absurl(self.config[setting])
             
             for setting in ('archives_url', 'assets_url', 'base_url', 'posts_url', 'tags_url'):
                 if re.search(r'(?:^\.{2}/|/\.{2}$|/\.{2}/)', self.config[setting]):
                     raise ConfigException('Invalid config setting.', 'setting: {0}'.format(setting), 'path traversal is not allowed')
             
             for pattern in self.config['include']:
                 if op.commonprefix((self.src.path, normpath(self.src.path, pattern))) != self.src.path:
                     raise ConfigException('Invalid include path.', 'path: {0}'.format(pattern), 'path traversal is not allowed')
             
             break
     else:
         logger.debug('..  no config file found')
Esempio n. 2
0
 def _get_path(self, url):
     parts = [self.dest.path] + url.split('/')
     
     if url.endswith('/'):
         parts.append('index.html')
     
     return normpath(*parts)
Esempio n. 3
0
    def _parse(self):
        logger.info('>> Parsing')
        
        path = Directory(normpath(self.src.path, '_posts'))
        
        logger.debug('..  src: %s', path)
        
        for i, f in enumerate(path):
            post = Post(f)
            
            content = self.parser.parse(self.renderer.from_string(post.bodymatter, post.frontmatter))
            excerpt = re.search(r'\A.*?(?:<p>(.+?)</p>)?', content, re.M | re.S).group(1)
            
            try:
                data = {
                    'content': content,
                    'date': post.date.strftime(self.config['date_format']).decode('utf-8'),
                    'excerpt': excerpt,
                    'tags': [],
                    'timestamp': timegm(post.date.utctimetuple()),
                    'url': self._get_post_url(post.date, post.slug),
                    'prev': False,
                    'next': False
                }
            except PageException:
                raise PageException('Invalid post slug.', 'src: {0}'.format(post.path))
            
            data.update(post.frontmatter)
            if len(data['tags']) == 0:
                data['tags'].append('_untagged') 
            else:
                data['tags'].sort()
            
            data['tags'] = [tag.title() for tag in data['tags']]

            data['title'] = str(data['title'])

            if post.draft:
                data['url'] = '/drafts/' + self._slugify(post.slug)
                self.drafts.append(data)
            else:
                self.posts.append(data)
                
                for tag in data['tags']:
                    if tag not in self.tags:
                        self.tags[tag] = []
                    
                    self.tags[tag].append(data)

        self.posts.sort(key = lambda post: post['timestamp'], reverse = True)
        for post in self.posts:
            if self.posts.index(post) != len(self.posts) - 1:
                prev = self.posts[self.posts.index(post) + 1]
                post['prev'] = {'title': prev['title'], 'url': prev['url']}
            
            if self.posts.index(post) != 0:
                next = self.posts[self.posts.index(post) - 1]
                post['next'] = {'title': next['title'], 'url': next['url']}
Esempio n. 4
0
 def _generate(self):
     logger.debug('>> Initializing\n..  src:  %s\n..  dest: %s', self.src.path, self.dest.path)
     
     self._update_config()
     
     if self.config['locale']:
         try:
             locale.setlocale(locale.LC_ALL, (self.config['locale'], 'utf-8'))
         except locale.Error:
             raise ConfigException('Locale not available.', 'run `locale -a` to see available locales')
     
     self.renderer.register({'site': self.config})
     
     self._render()
     
     logger.info('>> Generating')
     
     assets_src = Directory(normpath(self.src.path, '_assets'))
     assets_dest = Directory(normpath(self.dest.path, *self.config['assets_url'].split('/')))
     
     if self.dest.exists:
         if self.opts['force']:
             self.dest.empty()
         else:
             self.dest.rm()
     else:
         self.dest.mk()
     
     for page in self.pages:
         page.mk()
     
     assets_src.cp(assets_dest.path)
     
     for pattern in self.config['include']:
         for path in iglob(normpath(self.src.path, pattern)):
             dest = path.replace(self.src.path, self.dest.path)
             
             if op.isdir(path):
                 Directory(path).cp(dest, False)
             elif op.isfile(path):
                 File(path).cp(dest)
     
     logger.info('Completed in %.3fs', time() - self._start)
Esempio n. 5
0
File: fs.py Progetto: dkuntz2/fjord
 def __iter__(self):
     for root, dirs, files in walk(self.path):
         for d in dirs[:]:
             if d.startswith(('.', '_')):
                 dirs.remove(d)
         
         for f in files:
             if f.startswith(('.', '_')):
                 continue
             
             yield File(normpath(root, f))
Esempio n. 6
0
 def init(self):
     self.src = Directory(self._get_theme(self.opts['theme']))
     self.dest = Directory(self.opts['dest'])
     
     if not self.src.exists:
         raise OptionException('Theme not found.')
     elif self.dest.exists and not self.opts['force']:
         raise OptionException('Destination already exists.', 'the -f flag must be passed to force initialization by deleting the destination')
     
     logger.info('>> Initializing')
     
     if self.opts['bare']:
         self.dest.rm()
         
         for d in ('_assets/css', '_assets/images', '_assets/js', '_templates', '_posts'):
             Directory(normpath(self.dest.path, d)).mk()
         
         File(normpath(self.dest.path, 'config.yml')).mk()
     else:
         self.src.cp(self.dest.path, False)
     
     logger.info('Completed in %.3fs', time() - self._start)
Esempio n. 7
0
 def setup(self):
     self.config.update(self.options)
     self.config['loader'] = _PrefixLoader(OrderedDict([
         (op.sep, FileSystemLoader(self.path)),
         ('', FileSystemLoader(normpath(self.path, '_templates')))
     ]), None)
     
     self.environment = Environment(**self.config)
     
     self.environment.filters['absolutize'] = self._absolutize
     self.environment.filters['date'] = self._date
     
     self.environment.globals.update(self.globals)
     self.environment.globals['get_asset'] = self._get_asset
     self.environment.globals['get_url'] = self._get_url
     
     if 'extensions' in self.config and 'jinja2.ext.i18n' in self.config['extensions']:
         try:
             langs = [locale.getlocale(locale.LC_MESSAGES)[0].decode('utf-8')]
         except AttributeError:
             langs = None
         
         self.environment.install_gettext_translations(gettext.translation(gettext.textdomain(), normpath(self.path, '_locales'), langs, fallback = True))
Esempio n. 8
0
    def _render(self):
        self._process()
        
        logger.info('>> Rendering')
        
        self.renderer.register({
            'archives': self.archives,
            'posts': self.posts,
						'tags': self.tags
        })
        
        logger.debug('..  posts')
        
        for post in self.posts:
            try:
                self.pages.append(Page(
                    self._get_path(post['url']),
                    self._pygmentize(self.renderer.render(post['layout'], {'post': post}))
                ))
            except RendererException as e:
                raise RendererException(e.message, '{0} in post \'{1}\''.format(post['layout'], post['title']))
        
        logger.debug('..  drafts')
        for draft in self.drafts:
            try:
                self.pages.append(Page(
                    self._get_path(draft['url']),
                    self._pygmentize(self.renderer.render(post['layout'], {'post': post}))
                ))
            except RendererException as e:
                raise RendererException(e.message, '{0} in draft\'{1}\''.format(draft['layout'], draft['title']))

        logger.debug('..  pages')
        
        for f in self.src:
            if f.extension not in ('.html', '.htm', '.xml'):
                continue
            
            template = f.path.replace(self.src.path, '')
            
            self.pages.append(Page(
                normpath(self.dest.path, template),
                self._pygmentize(self.renderer.render(template))
            ))
        
        if self.config['tag_layout'] and self.tags:
            logger.debug('..  tags')
            
            for name, data in self.tags:
                self.pages.append(Page(
                    self._get_path(data['url']),
                    self._pygmentize(self.renderer.render(self.config['tag_layout'], {'tag': data}))
                ))
        
        if self.config['archive_layout'] and self.archives:
            logger.debug('..  archives')
            
            for year, data in self.archives:
                self.pages.append(Page(
                    self._get_path(data['url']),
                    self._pygmentize(self.renderer.render(self.config['archive_layout'], {'archive': data}))
                ))