Example #1
0
    def _parse_item(self, config, f, simple = False):
        Timer.start()

        item = Item(f.path)

        try:
            frontmatter, bodymatter = re.search(r'\A---\s+^(.+?)$\s+---\s*(.*)\Z', f.content, re.M | re.S).groups()
            frontmatter = Config(frontmatter)
        except AttributeError:
            raise ContentException('Invalid frontmatter.',
                'src: {0}'.format(f.path),
                'frontmatter must not be empty')
        except ConfigException:
            raise ConfigException('Invalid frontmatter.',
                'src: {0}'.format(f.path),
                'fontmatter contains invalid YAML')

        if 'layout' not in frontmatter:
            raise ContentException('Invalid frontmatter.',
                'src: {0}'.format(f.path),
                'layout must be set')

        parser = self._get_parser(f, frontmatter.get('parser', config.get('parser', None)))

        text, date = self._parse_filename(f)

        frontmatter.pop('url', None)
        frontmatter['slug'] = text

        result = parser.parse(self._writer.from_string(bodymatter, frontmatter))

        content, toc = result if isinstance(result, tuple) else (result, None)

        item['content'] = content
        item['date'] = date.strftime(self.site['date_format']).decode('utf-8')
        item['timestamp'] = timegm(date.utctimetuple())

        if toc is not None:
            item['toc'] = toc

        if simple:
            item['url'] = Url.from_path(f.root.path.replace(self.src.path, ''), text)
        else:
            item['excerpt'] = re.search(r'\A.*?(?:<p>(.+?)</p>)?', content, re.M | re.S).group(1)
            item['tags'] = []
            item['url'] = Url.from_format(config['url'], text, date, frontmatter)

        item.update(frontmatter)

        logger.debug('..  (%.3fs) %s', Timer.stop(), f.path.replace(self.src.path, ''))

        return item
Example #2
0
 def tag(self):
     tags = []
     
     for item in self.items:
         item['tags'].sort(key = unicode.lower)
         
         for tag in item['tags']:
             if tag not in self.tags:
                 self.tags[tag] = []
             
             self.tags[tag].append(item)
     
     for name, items in self.tags.iteritems():
         tags.append(Tag(
             name,
             Url.from_format(self.config['tags_url'], name),
             len(items),
             items,
             OrderedDict()
         ))
     
     self._sort(tags, 'name')
     self._sort(tags, 'count', 'desc')
     
     self.tags.clear()
     
     for tag in tags:
         self.tags[tag.name] = tag
Example #3
0
 def _parse_item(self, config, f, simple = False):
     Timer.start()
     
     item = Item(f.path)
     
     try:
         frontmatter, bodymatter = re.search(r'\A---\s+^(.+?)$\s+---\s*(.*)\Z', f.content, re.M | re.S).groups()
         frontmatter = Config(frontmatter)
     except AttributeError:
         raise ContentException('Invalid frontmatter.',
             'src: {0}'.format(f.path),
             'frontmatter must not be empty')
     except ConfigException:
         raise ConfigException('Invalid frontmatter.',
             'src: {0}'.format(f.path),
             'fontmatter contains invalid YAML')
     
     if 'layout' not in frontmatter:
         raise ContentException('Invalid frontmatter.',
             'src: {0}'.format(f.path),
             'layout must be set')
     
     frontmatter.pop('url', None)
     
     parser = self._get_parser(f, frontmatter.get('parser', config.get('parser', None)))
     
     text, date = self._parse_filename(f)
     content = parser.parse(self._writer.from_string(bodymatter, frontmatter))
     
     item['content'] = content
     item['date'] = date.strftime(self.site['date_format']).decode('utf-8')
     item['timestamp'] = timegm(date.utctimetuple())
     
     if simple:
         item['url'] = Url.from_path(f.root.path.replace(self.src.path, ''), text)
     else:
         item['excerpt'] = re.search(r'\A.*?(?:<p>(.+?)</p>)?', content, re.M | re.S).group(1)
         item['tags'] = []
         item['url'] = Url.from_format(config['url'], text, date, frontmatter)
     
     item.update(frontmatter)
     
     logger.debug('..  (%.3fs) %s', Timer.stop(), f.path.replace(self.src.path, ''))
     
     return item
Example #4
0
    def _get_url(self, url='', absolute=False):
        parts = [self.globals['site']['base_url'], url]
        domain = self.globals['site']['domain']

        if absolute and domain:
            if not domain.startswith(('http://', 'https://')):
                domain = 'http://' + domain

            parts.insert(0, domain)

        return Url.join(*parts)
Example #5
0
 def _get_url(self, url = '', absolute = False):
     parts = [self.globals['site']['base_url'], url]
     domain = self.globals['site']['domain']
     
     if absolute and domain:
         if not domain.startswith(('http://', 'https://')):
             domain = 'http://' + domain
         
         parts.insert(0, domain)
     
     return Url.join(*parts)
Example #6
0
 def _archive(self, items, archive):
     for item in items:
         year, month = datetime.utcfromtimestamp(item['timestamp']).strftime('%Y %B').decode('utf-8').split()
         
         if year not in archive:
             archive[year] = {
                 'months': OrderedDict({month: [item]}),
                 'url': Url.from_format(self.config['archives_url'], year),
                 'year': year
             }
         elif month not in archive[year]['months']:
             archive[year]['months'][month] = [item]
         else:
             archive[year]['months'][month].append(item)
Example #7
0
    def serve(self):
        self.src = Directory(self.opts['src'])
        base_url = Url.join(self.opts['base_url'], '')

        if not self.src.exists:
            raise OptionException('Source must exist.')

        logger.info('>> Serving at 127.0.0.1:%s', self.opts['port'])
        logger.info('Press ctrl+c to stop.')

        cwd = getcwd()
        self.server = Server(('', self.opts['port']), base_url, RequestHandler)

        chdir(self.src.path)

        try:
            self.server.serve_forever()
        except KeyboardInterrupt:
            self.server.shutdown()
            chdir(cwd)

            print('')
Example #8
0
    def serve(self):
        self.src = Directory(self.opts['src'])
        base_url = Url.join(self.opts['base_url'], '')

        if not self.src.exists:
            raise OptionException('Source must exist.')

        logger.info('>> Serving at 127.0.0.1:%s', self.opts['port'])
        logger.info('Press ctrl+c to stop.')

        cwd = getcwd()
        self.server = Server(('', self.opts['port']), base_url, RequestHandler)

        chdir(self.src.path)

        try:
            self.server.serve_forever()
        except KeyboardInterrupt:
            self.server.shutdown()
            chdir(cwd)

            print('')
Example #9
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'] = Url.join(self.config['assets_url'],
                                                     '')
                self.config['base_url'] = Url.join(
                    self.opts.get('base_url', self.config['base_url']), '')

                for setting in ('archives_url', 'posts_url', 'tags_url'):
                    self.config[setting] = Url.join(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')

                containers_src = normpath(self.src.path, '_containers')

                for name, config in self.config['containers'].iteritems():
                    if op.commonprefix(
                        (containers_src, normpath(containers_src,
                                                  name))) != containers_src:
                        raise ConfigException(
                            'Invalid config setting.',
                            'setting: containers:{0}'.format(name),
                            'container name contains illegal characters')

                    try:
                        url = Url.join(config['url'])
                    except KeyError:
                        raise ConfigException(
                            'Invalid config setting.',
                            'setting: containers:{0}'.format(name),
                            'url must be set for all containers')

                    if re.search(r'(?:^\.{2}/|/\.{2}$|/\.{2}/)', url):
                        raise ConfigException(
                            'Invalid config setting.',
                            'setting: containers:{0}:url'.format(name),
                            'path traversal is not allowed')

                    config.update(
                        (k, v) for k, v in self.container_defaults.iteritems()
                        if k not in config)
                    config['url'] = url

                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')
Example #10
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'] = Url.join(self.config['assets_url'], '')
                self.config['base_url'] = Url.join(self.opts.get('base_url', self.config['base_url']), '')

                for setting in ('archives_url', 'posts_url', 'tags_url'):
                    self.config[setting] = Url.join(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')

                containers_src = normpath(self.src.path, '_containers')

                for name, config in self.config['containers'].iteritems():
                    if op.commonprefix((containers_src, normpath(containers_src, name))) != containers_src:
                        raise ConfigException('Invalid config setting.',
                            'setting: containers:{0}'.format(name),
                            'container name contains illegal characters')

                    try:
                        url = Url.join(config['url'])
                    except KeyError:
                        raise ConfigException('Invalid config setting.',
                            'setting: containers:{0}'.format(name),
                            'url must be set for all containers')

                    if re.search(r'(?:^\.{2}/|/\.{2}$|/\.{2}/)', url):
                        raise ConfigException('Invalid config setting.',
                            'setting: containers:{0}:url'.format(name),
                            'path traversal is not allowed')

                    config.update((k, v) for k, v in self.container_defaults.iteritems() if k not in config)
                    config['url'] = url

                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')
Example #11
0
 def _get_asset(self, asset):
     return Url.join(self.globals['site']['base_url'],
                     self.globals['site']['assets_url'], asset)
Example #12
0
 def _get_asset(self, asset):
     return Url.join(self.globals['site']['base_url'], self.globals['site']['assets_url'], asset)
Example #13
0
 def _get_figure(self, slug, figure):
     return Url.join(self.globals['site']['base_url'],
                     self.globals['site']['figures_url'],
                     slug, figure)