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

        item = Item(f.path)

        try:
            matches = re.search(r'\A---\s+^(.+?)$\s+---\s*(.*)\Z', f.content,
                                re.M | re.S)
            frontmatter, bodymatter = matches.groups()
            frontmatter = Configuration(frontmatter)
        except AttributeError:
            raise ContentException('Invalid frontmatter',
                                   'src: {0}'.format(f.path),
                                   'frontmatter must not be empty')
        except ConfigurationException:
            raise ConfigurationException('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 = configuration.get('parser', None)
        parser = frontmatter.get('parser', parser)
        parser = self._get_parser(f, parser)

        text, date = self._parse_filename(f)
        content = self._writer.from_string(bodymatter, frontmatter)
        content = parser.parse(content)

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

        if simple:
            url = f.root.path.replace(self.source.path, '')

            item['url'] = URL.from_path(url, text)
        else:
            excerpt = re.search(r'\A.*?(?:<p>(.+?)</p>)?', content,
                                re.M | re.S).group(1)
            url = URL.from_format(configuration['url'], text, date,
                                  frontmatter)

            item['excerpt'] = excerpt
            item['tags'] = []
            item['url'] = url

        item.update(frontmatter)

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

        return item
Beispiel #2
0
    def _get_url(self, url='', absolute=False):
        parts = [self.globals['site']['base_url'], url]
        domain = self.globals['site']['domain']

        if absolute and domain:
            parts.insert(0, domain)

        return URL.join(*parts)
Beispiel #3
0
    def _archive(self, items, archive):
        for item in items:
            timestamp = datetime.utcfromtimestamp(item['timestamp'])
            year, month = timestamp.strftime('%Y %B').split()

            if year not in archive:
                months = OrderedDict({month: [item]})
                url = URL.from_format(self.configuration['archives_url'], year)

                archive[year] = {'months': months, 'url': url, 'year': year}
            elif month not in archive[year]['months']:
                archive[year]['months'][month] = [item]
            else:
                archive[year]['months'][month].append(item)
Beispiel #4
0
    def serve(self):
        self.source = Directory(self.options['source'])

        if not self.source.exists:
            raise OptionException('Source directory does not exist')

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

        address = ('', self.options['port'])
        base_url = URL.join(self.options['base_url'], '')
        cwd = getcwd()

        chdir(self.source.path)

        try:
            self.server = Server(address, base_url, RequestHandler)
            self.server.serve_forever()
        except KeyboardInterrupt:
            self.server.shutdown()
            chdir(cwd)

            print('')
Beispiel #5
0
    def tag(self):
        tags = []

        for item in self.items:
            item['tags'].sort(key=str.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.items():
            url = URL.from_format(self.configuration['tags_url'], name)

            tags.append(Tag(name, url, 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
Beispiel #6
0
    def _update_configuration(self):
        self.configuration = deepcopy(self.defaults)

        logger.info('>> Searching for configuration file')

        for configuration in product(('mynt', 'config'), ('.yml', '.yaml')):
            configuration = ''.join(configuration)
            configuration = File(normpath(self.source.path, configuration))
            if not configuration.exists:
                continue

            logger.debug('..  found: %s', configuration.path)

            if configuration.name == 'config':
                logger.warn('@@ Deprecated configuration file found')
                logger.warn('..  rename config.yml to mynt.yml')

            break
        else:
            logger.debug('..  no configuration file found')

            return

        try:
            self.configuration.update(Configuration(configuration.content))
        except ConfigurationException as error:
            raise ConfigurationException(
                error.message, 'source: {0}'.format(configuration.path))

        domain = self.configuration['domain']
        if domain and not domain.startswith(('https://', 'http://', '//')):
            logger.warn('@@ Configuration setting `domain` missing protocol')
            logger.warn('..  defaulting to `https`')

            self.configuration['domain'] = 'https://{0}'.format(domain)

        self.configuration['base_url'] = self.options.get('base_url')
        self.configuration['locale'] = self.options.get('locale')

        options = ('archives_url', 'assets_url', 'base_url', 'posts_url',
                   'tags_url')

        for option in options:
            url = URL.join(self.configuration[option], '')
            if re.search(r'(?:^\.{2}/|/\.{2}$|/\.{2}/)', url):
                raise ConfigurationException(
                    'Invalid configuration option',
                    'option: {0}'.format(self.configuration[option]),
                    'path traversal is not allowed')

        containers_source = normpath(self.source.path, '_containers')

        for name, options in self.configuration['containers'].items():
            prefix = op.commonprefix(
                (containers_source, normpath(containers_source, name)))
            if prefix != containers_source:
                raise ConfigurationException(
                    'Invalid configuration option',
                    'setting: containers:{0}'.format(name),
                    'container name contains illegal characters')

            try:
                url = URL.join(options['url'])
            except KeyError:
                raise ConfigurationException(
                    'Invalid configuration option',
                    'setting: containers:{0}'.format(name),
                    'url must be set for all containers')

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

            for name, value in self.container_defaults.items():
                if name not in options:
                    options[name] = value

            options['url'] = url

        for pattern in self.configuration['include']:
            prefix = op.commonprefix(
                (self.source.path, normpath(self.source.path, pattern)))
            if prefix != self.source.path:
                raise ConfigurationException('Invalid include path',
                                             'path: {0}'.format(pattern),
                                             'path traversal is not allowed')
Beispiel #7
0
    def _get_asset(self, asset):
        assets_url = self.globals['site']['assets_url']
        base_url = self.globals['site']['base_url']

        return URL.join(base_url, assets_url, asset)