Exemple #1
0
def _build_theme_template(template_name, env, files, config, nav):
    """ Build a template using the theme environment. """

    log.debug("Building theme template: {}".format(template_name))

    try:
        template = env.get_template(template_name)
    except TemplateNotFound:
        log.warning(
            "Template skipped: '{}' not found in theme directories.".format(
                template_name))
        return

    output = _build_template(template_name, template, files, config, nav)

    if output.strip():
        output_path = os.path.join(config['site_dir'], template_name)
        utils.write_file(output.encode('utf-8'), output_path)

        if template_name == 'sitemap.xml':
            log.debug("Gzipping template: %s", template_name)
            gz_filename = '{}.gz'.format(output_path)
            with open(gz_filename, 'wb') as f:
                timestamp = utils.get_build_timestamp()
                with gzip.GzipFile(fileobj=f,
                                   filename=gz_filename,
                                   mode='wb',
                                   mtime=timestamp) as gz_buf:
                    gz_buf.write(output.encode('utf-8'))
    else:
        log.info("Template skipped: '{}' generated empty output.".format(
            template_name))
Exemple #2
0
    def on_config(self, config: config_options.Config) -> dict:
        """The config event is the first event called on build and
        is run immediately after the user configuration is loaded and validated.
        Any alterations to the config should be made here.
        https://www.mkdocs.org/user-guide/plugins/#on_config

        :param config: global configuration object
        :type config: config_options.Config

        :raises FileExistsError: if the template for the RSS feed is not found

        :return: plugin configuration object
        :rtype: dict
        """

        # Skip if disabled
        if not self.config.get("enabled"):
            return config

        # check template dirs
        if not Path(DEFAULT_TEMPLATE_FILENAME).is_file():
            raise FileExistsError(DEFAULT_TEMPLATE_FILENAME)
        self.tpl_file = Path(DEFAULT_TEMPLATE_FILENAME)
        self.tpl_folder = DEFAULT_TEMPLATE_FOLDER

        # start a feed dictionary using global config vars
        base_feed = {
            "author": config.get("site_author", None),
            "buildDate": formatdate(get_build_timestamp()),
            "copyright": config.get("copyright", None),
            "description": config.get("site_description", None),
            "entries": [],
            "generator": "{} - v{}".format(__title__, __version__),
            "html_url": self.util.get_site_url(config),
            "language": self.util.guess_locale(config),
            "pubDate": formatdate(get_build_timestamp()),
            "repo_url": config.get("repo_url", config.get("site_url", None)),
            "title": config.get("site_name", None),
            "ttl": self.config.get("feed_ttl", None),
        }

        # feed image
        if self.config.get("image"):
            base_feed["logo_url"] = self.config.get("image")

        # pattern to match pages included in output
        self.match_path_pattern = compile(self.config.get("match_path"))

        # date handling
        if self.config.get("date_from_meta") is not None:
            self.src_date_created = self.config.get("date_from_meta").get(
                "as_creation", False
            )
            self.src_date_updated = self.config.get("date_from_meta").get(
                "as_update", False
            )
            self.meta_datetime_format = self.config.get("date_from_meta").get(
                "datetime_format", "%Y-%m-%d %H:%M"
            )
            logger.debug(
                "[rss-plugin] Dates will be retrieved from page meta (yaml "
                "frontmatter). The git log will be used as fallback."
            )
        else:
            logger.debug("[rss-plugin] Dates will be retrieved from git log.")

        # create 2 final dicts
        self.feed_created = deepcopy(base_feed)
        self.feed_updated = deepcopy(base_feed)

        # final feed url
        if base_feed.get("html_url"):
            # concatenate both URLs
            self.feed_created["rss_url"] = (
                base_feed.get("html_url") + OUTPUT_FEED_CREATED
            )
            self.feed_updated["rss_url"] = (
                base_feed.get("html_url") + OUTPUT_FEED_UPDATED
            )
        else:
            logging.warning(
                "[rss-plugin] The variable `site_url` is not set in the MkDocs "
                "configuration file whereas a URL is mandatory to publish. "
                "See: https://validator.w3.org/feed/docs/rss2.html#requiredChannelElements"
            )
            self.feed_created["rss_url"] = self.feed_updated["rss_url"] = None

        # ending event
        return config
Exemple #3
0
    def get_file_dates(
        self,
        in_page: Page,
        source_date_creation: str = "git",
        source_date_update: str = "git",
        meta_datetime_format: str = "%Y-%m-%d %H:%M",
    ) -> Tuple[int, int]:
        """Extract creation and update dates from page metadata (yaml frontmatter) or \
            git log for given file.

        :param in_page: input page to work with
        :type in_page: Page
        :param source_date_creation: which source to use (git or meta tag) for creation \
            date, defaults to "git"
        :type source_date_creation: str, optional
        :param source_date_update: which source to use (git or meta tag) for update \
            date, defaults to "git"
        :type source_date_update: str, optional
        :param meta_datetime_format: datetime string format, defaults to "%Y-%m-%d %H:%M"
        :type meta_datetime_format: str, optional

        :return: tuple of timestamps (creation date, last commit date)
        :rtype: Tuple[int, int]
        """
        # empty vars
        dt_created = dt_updated = None

        # if enabled, try to retrieve dates from page metadata
        if source_date_creation != "git" and in_page.meta.get(source_date_creation):
            dt_created = self.get_date_from_meta(
                date_metatag_value=in_page.meta.get(source_date_creation),
                meta_datetime_format=meta_datetime_format,
            )
            if isinstance(dt_created, str):
                logger.error(dt_created)
                dt_created = None

        if source_date_update != "git" and in_page.meta.get(source_date_update):
            dt_updated = self.get_date_from_meta(
                date_metatag_value=in_page.meta.get(source_date_creation),
                meta_datetime_format=meta_datetime_format,
            )
            if isinstance(dt_updated, str):
                logger.error(dt_updated)
                dt_updated = None

        # explore git log
        if self.git_is_valid:
            try:
                # only if dates have not been retrieved from page meta
                if not dt_created:
                    dt_created = self.repo.log(
                        in_page.file.abs_src_path,
                        n=1,
                        date="short",
                        format="%at",
                        diff_filter="AR",
                    )
                if not dt_updated:
                    dt_updated = self.repo.log(
                        in_page.file.abs_src_path,
                        n=1,
                        date="short",
                        format="%at",
                    )
            except GitCommandError as err:
                logging.warning(
                    "[rss-plugin] Unable to read git logs of '%s'. Is git log readable?"
                    " Falling back to build date. "
                    " Trace: %s" % (in_page.file.abs_src_path, err)
                )
            except GitCommandNotFound as err:
                logging.error(
                    "[rss-plugin] Unable to perform command 'git log'. Is git installed? "
                    " Falling back to build date. "
                    " Trace: %s" % err
                )
                self.git_is_valid = 0
        else:
            pass

        # return results
        if all([dt_created, dt_updated]):
            return (
                int(dt_created),
                int(dt_updated),
            )
        else:
            logging.warning(
                "[rss-plugin] Dates could not be retrieved for page: %s."
                % in_page.file.abs_src_path
            )
            return (
                get_build_timestamp(),
                get_build_timestamp(),
            )