Пример #1
0
    def _split_content_with_frontmatter(self, first, source, source_file):
        """Separate frontmatter from source material."""
        max_splits = 1
        # With a directive present, there must be two document markers.
        if first.startswith('%YAML'):
            max_splits = 2
        content = source.split(self.document_marker, max_splits)

        try:
            data = yaml.load(content[max_splits - 1])
        except ScannerError as ex:
            raise AbortError(
                _('There is invalid YAML in the frontmatter: {details}').
                format(details=str(ex)))
        try:
            source = content[max_splits]
        except IndexError:
            raise AbortError(
                _('A YAML marker was missing in {source}').format(
                    source=source_file))

        if 'title' in data:
            data['title'] = escape(data['title'])

        return data, source
Пример #2
0
def make(scaffold, site):
    """Make a site from the scaffold."""
    if scaffold not in BUILTIN_SCAFFOLDS:
        raise AbortError(
            _('There is no {scaffold} scaffold.'.format(scaffold=scaffold)))
    if os.path.exists(site):
        raise AbortError(_('{site} already exists.'.format(site=site)))
    os.makedirs(site)
    scaffold_path = os.path.join(SCAFFOLDS_PATH, scaffold)
    shutil.copytree(scaffold_path, os.path.join(site, 'source'))
Пример #3
0
    def on_pre_composition(self, director):
        if not self._config.parser.has_section('open_graph'):
            raise AbortError(
                _('An open_graph section is missing in the configuration file.'
                  ))

        if not self._config.parser.has_option('open_graph', 'default_image'):
            raise AbortError(
                _('A default image URL is missing in the configuration file.'))

        self._resolver = director.resolver
        self._url_resolver = URLResolver(
            self._config, self._config.parser.get('open_graph',
                                                  'default_image'))
Пример #4
0
 def build(cls, args):
     """Build a validated site."""
     site = cls(args.site)
     valid, message = site.is_valid()
     if not valid:
         raise AbortError(_('Invalid site source: {0}').format(message))
     return site
Пример #5
0
    def on_pre_composition(self, director):
        if not self._config.parser.has_section('twitter'):
            raise AbortError(
                _('An twitter section is missing in the configuration file.'))

        if not self._config.parser.has_option('twitter', 'default_image'):
            raise AbortError(
                _('A default image URL is missing in the configuration file.'))

        if not self._config.parser.has_option('twitter', 'site_username'):
            raise AbortError(
                _('A site username is missing in the configuration file.'))

        self._resolver = director.resolver
        self._url_resolver = URLResolver(
            self._config, self._config.parser.get('twitter', 'default_image'))
        self._site = self._config.parser.get('twitter', 'site_username')
Пример #6
0
 def _is_post(self, frontmatter):
     """Check if the front matter looks like a blog post."""
     is_post = frontmatter.get("blog", False)
     if type(is_post) != bool:
         raise AbortError(
             _("Invalid blog frontmatter (expects True or False): "
               "{blog_value}").format(blog_value=is_post))
     return is_post
Пример #7
0
 def _get_option(self, option):
     """Get an option out of the blog section."""
     try:
         return self._config.parser.get("blog", option)
     except configparser.NoOptionError:
         raise AbortError(
             _("The blog extension requires the {option} option.").format(
                 option=option))
Пример #8
0
    def _build_template(self, template_path):
        """Build a template. Abort if unknown type."""
        for extension, template_builder in self._builders.items():
            if template_path.endswith(extension):
                return template_builder(template_path)

        raise AbortError(
            _('Unknown template type provided for {template}.').format(
                template=template_path))
Пример #9
0
 def _validate_post(self, source_file, frontmatter):
     """Validate that the post contains all the required fields."""
     required = set(["date", "title"])
     fields = set(frontmatter.keys())
     missing = required - fields
     if missing:
         raise AbortError(
             _("The blog post, {filename}, "
               "is missing required fields: {missing_fields}".format(
                   filename=source_file,
                   missing_fields=", ".join(missing))))
Пример #10
0
 def _find_extensions(self, parser):
     """Check if the site options have extensions to enable."""
     for option in parser.options('site'):
         if option.startswith('with_'):
             try:
                 extension = option.split('with_', 1)[1] or option
                 enabled = parser.getboolean('site', option)
                 if enabled:
                     self.active_extensions.add(extension)
             except ValueError:
                 raise AbortError(
                     _('Cannot determine if {extension} is enabled.').
                     format(extension=extension))
Пример #11
0
 def _validate_post(self, source_file, frontmatter):
     """Validate that the post contains all the required fields."""
     required = set([
         'date',
         'title',
     ])
     fields = set(frontmatter.keys())
     missing = required - fields
     if missing:
         raise AbortError(
             _('The blog post, {filename}, '
               'is missing required fields: {missing_fields}'.format(
                   filename=source_file,
                   missing_fields=', '.join(missing))))
Пример #12
0
 def build(self, template_path):
     """Build a Jinja template from the file path."""
     # Strip the templates path from the template path to get the relative
     # name that the ``FileSystemLoader`` wants.
     template_name = os.path.relpath(template_path, self.templates_path)
     try:
         template = self._env.get_template(template_name)
         template.last_modified = self._get_last_modified(template_name,
                                                          template_path)
         return template
     except jinja2.exceptions.TemplateSyntaxError as e:
         raise AbortError(
             _('An error exists in the Jinja template at {template}:'
               ' {error}').format(template=template_path, error=str(e)))
Пример #13
0
    def on_pre_composition(self, director):
        """Check that all the required configuration exists."""
        if not self._config.parser.has_section("blog"):
            raise AbortError(
                _("A blog section is missing in the configuration file."))

        # Collect atom feed configuration.
        for metadata, option in self.required_metadata.items():
            self._add_atom_metadata(metadata, option)
        self.atom_output = self._get_option("atom_output")

        # Collect HTML listing configuration.
        if self._config.parser.has_option("blog", "list_template"):
            self.list_template = self._get_option("list_template")
            self.list_output = self._get_option("list_output")

        # Grab the resolver from the director for determining URLs for posts.
        self._resolver = director.resolver
Пример #14
0
    def _find_site_root_from(self, cwd):
        """Ascend through the current working directory provided to find
        something that looks like the root of a handroll site and return that
        path. Assumes that ``cwd`` is a valid directory path."""
        candidate = cwd
        while True:
            if self._is_site_root(candidate):
                return candidate

            parent = os.path.realpath(os.path.join(candidate, os.pardir))
            if candidate == parent:
                # When the next candidate is equal to the previous one, then
                # the root of the filesystem has been reached and tested.
                break

            candidate = parent

        raise AbortError(
            _('A handroll site was not found in {current_directory}'
              ' or any of its parents.').format(current_directory=cwd))
Пример #15
0
    def _parse_feed(self, source_file):
        try:
            with io.open(source_file, "r", encoding="utf-8") as f:
                metadata = json.loads(f.read())

            if metadata.get("entries") is None:
                raise ValueError(_("Missing entries list."))

            entries = metadata["entries"]
            # AtomFeed expects FeedEntry objects for the entries keyword so
            # remove it from the metadata and add it after the feed is built.
            del metadata["entries"]

            feed = AtomFeed(**metadata)
            [feed.add(self._make_entry(entry)) for entry in entries]
        except ValueError as error:
            raise AbortError(
                _("Invalid feed {source_file}: {error}").format(
                    source_file=source_file, error=str(error)))

        return feed
Пример #16
0
    def compose(self, catalog, source_file, out_dir):
        root, ext = os.path.splitext(os.path.basename(source_file))
        filename = root + self.output_extension
        output_file = os.path.join(out_dir, filename)

        logger.info(
            _('Generating CSS for {source_file} ...').format(
                source_file=source_file))

        command = self.build_command(source_file, output_file)
        process = subprocess.Popen(command,
                                   stdin=subprocess.PIPE,
                                   stdout=subprocess.PIPE)
        (out, err) = process.communicate()

        if out:
            logger.debug(_('Received output from sass:\n{0}'.format(out)))

        if process.returncode != 0:
            raise AbortError(
                _('Sass failed to generate CSS:\n{0}').format(err))
Пример #17
0
 def domain(self):
     if self._domain is None:
         raise AbortError(
             _('You are missing a domain setting in the site section.'))
     return self._domain
Пример #18
0
 def _abort_if_missing(self, template_path):
     if not os.path.exists(template_path):
         raise AbortError(
             _('No template found at {template_path}.').format(
                 template_path=template_path))
Пример #19
0
 def __init__(self, path=None):
     self.sass = spawn.find_executable('sass', path)
     if self.sass is None:
         raise AbortError(_('Sass is not installed.'))