예제 #1
0
    def on_post_build(self, config):
        sources = set(self.sources)
        log.debug('Found {} unique sources in {} total embeds'.format(
            len(sources), len(self.sources)))
        self.sources = []

        for source in sources:
            dest_rel_path = '{}-{}.{}'.format(source.source_rel,
                                              source.page_index,
                                              self.config['format'])
            abs_src_path = os.path.join(config['docs_dir'], source.source_rel)
            abs_dest_path = os.path.join(config['site_dir'], dest_rel_path)
            cache_filename, exit_status = self.exporter.ensure_file_cached(
                abs_src_path, source.source_rel, source.page_index,
                self.config['drawio_executable'], self.config['drawio_args'],
                self.config['cache_dir'], self.config['format'])

            if exit_status not in (None, 0):
                log.error(
                    'Export failed with exit status {}; skipping copy'.format(
                        exit_status))
                continue

            try:
                copy_file(cache_filename, abs_dest_path)
            except FileNotFoundError:
                log.warn('Export successful, but wrote no output file')
예제 #2
0
    def test_copy_files_without_permissions(self):
        src_paths = [
            'foo.txt',
            'bar.txt',
            'baz.txt',
        ]
        expected = [
            'foo.txt',
            'bar.txt',
            'baz.txt',
        ]

        src_dir = tempfile.mkdtemp()
        dst_dir = tempfile.mkdtemp()

        try:
            for i, src in enumerate(src_paths):
                src = os.path.join(src_dir, src)
                with open(src, 'w') as f:
                    f.write('content')
                # Set src file to read-only
                os.chmod(src, stat.S_IRUSR)
                utils.copy_file(src, dst_dir)
                self.assertTrue(os.path.isfile(os.path.join(dst_dir, expected[i])))
                self.assertNotEqual(os.stat(src).st_mode, os.stat(os.path.join(dst_dir, expected[i])).st_mode)
                # While src was read-only, dst must remain writable
                self.assertTrue(os.access(os.path.join(dst_dir, expected[i]), os.W_OK))
        finally:
            for src in src_paths:
                # Undo read-only so we can delete temp files
                src = os.path.join(src_dir, src)
                if os.path.exists(src):
                    os.chmod(src, stat.S_IRUSR | stat.S_IWUSR)
            shutil.rmtree(src_dir)
            shutil.rmtree(dst_dir)
예제 #3
0
    def on_post_build(self, config, **kwargs):
        "Build search index."
        output_base_path = os.path.join(config['site_dir'], 'search')
        search_index = self.search_index.generate_search_index()
        json_output_path = os.path.join(output_base_path, 'search_index.json')
        utils.write_file(search_index.encode('utf-8'), json_output_path)

        if not ('search_index_only' in config['theme']
                and config['theme']['search_index_only']):
            # Include language support files in output. Copy them directly
            # so that only the needed files are included.
            files = []
            if len(self.config['lang']) > 1 or 'en' not in self.config['lang']:
                files.append('lunr.stemmer.support.js')
            if len(self.config['lang']) > 1:
                files.append('lunr.multi.js')
            if ('ja' in self.config['lang'] or 'jp' in self.config['lang']):
                files.append('tinyseg.js')
            for lang in self.config['lang']:
                if (lang != 'en'):
                    files.append('lunr.{}.js'.format(lang))

            for filename in files:
                from_path = os.path.join(base_path, 'lunr-language', filename)
                to_path = os.path.join(output_base_path, filename)
                utils.copy_file(from_path, to_path)
예제 #4
0
    def on_post_build(self, config, **kwargs):
        output_base_path = os.path.join(config['site_dir'], 'search')
        input_base_path = os.path.join(base_path, 'search')

        to_path = os.path.join(output_base_path, 'main.js')
        from_path = os.path.join(input_base_path, 'main.js')
        utils.copy_file(from_path, to_path)
예제 #5
0
 def copy_file(self, dirty=False):
     """ Copy source file to destination, ensuring parent directories exist. """
     if dirty and not self.is_modified():
         log.debug("Skip copying unmodified file: '{}'".format(self.src_path))
     else:
         log.debug("Copying media file: '{}'".format(self.src_path))
         utils.copy_file(self.abs_src_path, self.abs_dest_path)
예제 #6
0
    def test_copy_files(self):
        src_paths = [
            'foo.txt',
            'bar.txt',
            'baz.txt',
        ]
        dst_paths = [
            'foo.txt',
            'foo/',             # ensure src filename is appended
            'foo/bar/baz.txt'   # ensure missing dirs are created
        ]
        expected = [
            'foo.txt',
            'foo/bar.txt',
            'foo/bar/baz.txt',
        ]

        src_dir = tempfile.mkdtemp()
        dst_dir = tempfile.mkdtemp()

        try:
            for i, src in enumerate(src_paths):
                src = os.path.join(src_dir, src)
                with open(src, 'w') as f:
                    f.write('content')
                dst = os.path.join(dst_dir, dst_paths[i])
                utils.copy_file(src, dst)
                self.assertTrue(os.path.isfile(os.path.join(dst_dir, expected[i])))
        finally:
            shutil.rmtree(src_dir)
            shutil.rmtree(dst_dir)
예제 #7
0
    def test_copy_files(self):
        src_paths = [
            'foo.txt',
            'bar.txt',
            'baz.txt',
        ]
        dst_paths = [
            'foo.txt',
            'foo/',             # ensure src filename is appended
            'foo/bar/baz.txt'   # ensure missing dirs are created
        ]
        expected = [
            'foo.txt',
            'foo/bar.txt',
            'foo/bar/baz.txt',
        ]

        src_dir = tempfile.mkdtemp()
        dst_dir = tempfile.mkdtemp()

        try:
            for i, src in enumerate(src_paths):
                src = os.path.join(src_dir, src)
                with open(src, 'w') as f:
                    f.write('content')
                dst = os.path.join(dst_dir, dst_paths[i])
                utils.copy_file(src, dst)
                self.assertTrue(os.path.isfile(os.path.join(dst_dir, expected[i])))
        finally:
            shutil.rmtree(src_dir)
            shutil.rmtree(dst_dir)
예제 #8
0
    def test_copy_files_without_permissions(self):
        src_paths = [
            'foo.txt',
            'bar.txt',
            'baz.txt',
        ]
        expected = [
            'foo.txt',
            'bar.txt',
            'baz.txt',
        ]

        src_dir = tempfile.mkdtemp()
        dst_dir = tempfile.mkdtemp()

        try:
            for i, src in enumerate(src_paths):
                src = os.path.join(src_dir, src)
                with open(src, 'w') as f:
                    f.write('content')
                # Set src file to read-only
                os.chmod(src, stat.S_IRUSR)
                utils.copy_file(src, dst_dir)
                self.assertTrue(os.path.isfile(os.path.join(dst_dir, expected[i])))
                self.assertNotEqual(os.stat(src).st_mode, os.stat(os.path.join(dst_dir, expected[i])).st_mode)
                # While src was read-only, dst must remain writable
                self.assertTrue(os.access(os.path.join(dst_dir, expected[i]), os.W_OK))
        finally:
            for src in src_paths:
                # Undo read-only so we can delete temp files
                src = os.path.join(src_dir, src)
                if os.path.exists(src):
                    os.chmod(src, stat.S_IRUSR | stat.S_IWUSR)
            shutil.rmtree(src_dir)
            shutil.rmtree(dst_dir)
예제 #9
0
파일: __init__.py 프로젝트: k4kfh/mkdocs
    def on_post_build(self, config, **kwargs):
        "Build search index."
        output_base_path = os.path.join(config['site_dir'], 'search')

        if self.config['local_search_shim']:
            print(
                "INFO    -   local_search_shim Enabled! Make sure you've added shims/fetch_shim.js to your docs folder."
            )
            # Change the search_index from being pure JSON to being JavaScript containing a global searchIndex variable with the JSON object we want
            # Also write it in the traditional format, so that either way works
            search_index = self.search_index.generate_search_index()
            search_index_shimmed = "shim_localSearchIndex = " + search_index
            json_output_path = os.path.join(output_base_path,
                                            'search_index.json')
            json_output_path_shimmed = os.path.join(output_base_path,
                                                    'search_index.js')
            utils.write_file(search_index.encode('utf-8'), json_output_path)
            utils.write_file(search_index_shimmed.encode('utf-8'),
                             json_output_path_shimmed)
        else:
            # Write the search index only in the traditional way
            print(
                "INFO    -   local_search_shim disabled. Generating only traditional JSON search index..."
            )
            search_index = self.search_index.generate_search_index()
            json_output_path = os.path.join(output_base_path,
                                            'search_index.json')
            utils.write_file(search_index.encode('utf-8'), json_output_path)

        if not ('search_index_only' in config['theme']
                and config['theme']['search_index_only']):
            # Include language support files in output. Copy them directly
            # so that only the needed files are included.
            files = []
            if len(self.config['lang']) > 1 or 'en' not in self.config['lang']:
                files.append('lunr.stemmer.support.js')
            if len(self.config['lang']) > 1:
                files.append('lunr.multi.js')
            for lang in self.config['lang']:
                if (lang != 'en'):
                    files.append('lunr.{}.js'.format(lang))

            for filename in files:
                from_path = os.path.join(base_path, 'lunr-language', filename)
                to_path = os.path.join(output_base_path, filename)
                utils.copy_file(from_path, to_path)
예제 #10
0
    def on_post_build(self, config: Dict[str, Any], **kwargs) -> None:
        """
        Run on post build.

        Adds the timeago assets to the build.
        """
        # Add timeago files:
        if self.config.get("type") == "timeago" and self.config.get('enabled'):
            files = [
                "js/timeago.min.js",
                "js/timeago_mkdocs_material.js",
                "css/timeago.css",
            ]
            for file in files:
                dest_file_path = os.path.join(config["site_dir"], file)
                src_file_path = os.path.join(HERE, file)
                assert os.path.exists(src_file_path)
                copy_file(src_file_path, dest_file_path)
예제 #11
0
    def on_post_build(self, config):
        sources = set(self.sources)
        log.debug('Found {} unique sources in {} total embeds'.format(
            len(sources), len(self.sources)))
        self.sources = []

        for source in sources:
            dest_rel_path = '{}-{}.{}'.format(source.source_rel,
                                              source.page_index,
                                              self.config['format'])
            abs_src_path = os.path.join(config['docs_dir'], source.source_rel)
            abs_dest_path = os.path.join(config['site_dir'], dest_rel_path)
            cache_filename = self.exporter.ensure_file_cached(
                abs_src_path, source.source_rel, source.page_index,
                self.config['drawio_executable'], self.config['cache_dir'],
                self.config['format'])

            try:
                copy_file(cache_filename, abs_dest_path)
            except FileNotFoundError:
                log.exception('Output file not created in cache')
예제 #12
0
    def on_page_content(self, content, page, config, files):
        if not self.can_load(page.file.abs_src_path):
            return content

        exp = HTMLExporter()

        exp.template_file = self.template_file.name
        ipynb_path = page.file.abs_src_path
        nb = nbformat.read(ipynb_path, as_version=4)

        exporter_resources = {
            'filename': os.path.split(page.file.abs_src_path)[1],
        }
        (body,
         resources) = exp.from_notebook_node(nb, resources=exporter_resources)

        # copy the notebook itself into the destination too
        nb_name = os.path.split(page.file.abs_src_path)[1]
        b = os.path.join(os.path.split(page.file.abs_dest_path)[0], nb_name)
        utils.copy_file(ipynb_path, b)

        return body
예제 #13
0
    def on_post_build(self, config, **kwargs):
        "Build search index."
        output_base_path = os.path.join(config['site_dir'], 'search')
        search_index = self.search_index.generate_search_index()
        json_output_path = os.path.join(output_base_path, 'search_index.json')
        utils.write_file(search_index.encode('utf-8'), json_output_path)

        if not ('search_index_only' in config['theme'] and config['theme']['search_index_only']):
            # Include language support files in output. Copy them directly
            # so that only the needed files are included.
            files = []
            if len(self.config['lang']) > 1 or 'en' not in self.config['lang']:
                files.append('lunr.stemmer.support.js')
            if len(self.config['lang']) > 1:
                files.append('lunr.multi.js')
            for lang in self.config['lang']:
                if (lang != 'en'):
                    files.append('lunr.{}.js'.format(lang))

            for filename in files:
                from_path = os.path.join(base_path, 'lunr-language', filename)
                to_path = os.path.join(output_base_path, filename)
                utils.copy_file(from_path, to_path)
예제 #14
0
파일: hooks.py 프로젝트: twpayne/chezmoi
def on_post_build(config, **kwargs):
    site_dir = config['site_dir']

    # copy GitHub pages config
    utils.copy_file('CNAME', os.path.join(site_dir, 'CNAME'))

    # copy installation scripts
    utils.copy_file('../scripts/install.sh', os.path.join(site_dir, 'get'))
    utils.copy_file('../scripts/install.ps1',
                    os.path.join(site_dir, 'get.ps1'))
예제 #15
0
    def on_post_build(self, config):

        # Add print-site.js
        js_output_base_path = os.path.join(config["site_dir"], "js")
        js_file_path = os.path.join(js_output_base_path, "print-site.js")
        copy_file(os.path.join(os.path.join(HERE, "js"), "print-site.js"),
                  js_file_path)

        # Add print-site.css
        css_output_base_path = os.path.join(config["site_dir"], "css")
        css_file_path = os.path.join(css_output_base_path, "print-site.css")
        copy_file(os.path.join(os.path.join(HERE, "css"), "print-site.css"),
                  css_file_path)
        # Add theme CSS file
        css_file = "print-site-%s.css" % config.get("theme").name
        if css_file in os.listdir(os.path.join(HERE, "css")):
            css_file_path = os.path.join(css_output_base_path, css_file)
            copy_file(os.path.join(os.path.join(HERE, "css"), css_file),
                      css_file_path)

        # Determine calls to required javascript functions
        js_calls = ""
        if config.get("theme").name == "material":
            js_calls += "change_material_theme('default');"
        if self.config.get("add_table_of_contents"):
            js_calls += "generate_toc();"

        # Add JS file for compatibility for mkdocs-material instant loading
        # note this is inserted to all mkdocs pages,
        # because each page can be the start of instant loading session
        js_instant_loading = ("""
         // Subscribe functions for compatibility 
         // with mkdocs-material's instant loading feature
         
         body = document.getElementsByTagName('body')[0];
         mkdocs_material_site_color_theme = body.getAttribute('data-md-color-scheme');
                    
         if (
            typeof app !== "undefined" && 
            typeof app.document$ !== "undefined"
            ) {
            app.document$.subscribe(function() {
                if ( document.querySelector("#print-site-page") !== null ) {
                    %s
                } else {
                    // Make sure to change the color theme back!
                    if ( mkdocs_material_site_color_theme !== null ) {
                        change_material_theme(mkdocs_material_site_color_theme);   
                    }
                }
            })
         }
        """ % js_calls)
        write_file(
            js_instant_loading.encode("utf-8", errors="xmlcharrefreplace"),
            os.path.join(js_output_base_path, "print-site-instant-loading.js"),
        )

        # Combine the HTML of all pages present in the navigation
        self.print_page.content = self.renderer.write_combined()

        # Get the info for MkDocs to be able to apply a theme template on our print page
        env = config["theme"].get_env()
        template = env.get_template("main.html")
        self.context["page"] = self.print_page
        # Render the theme template for the print page
        html = template.render(self.context)

        # Inject JS into print page
        print_site_js = ("""
        <script type="text/javascript">
        window.addEventListener('load', function () {
            %s
        })
        </script>
        """ % js_calls)
        html = html.replace("</body>", print_site_js + "</body>")

        # Write the print_page file to the output folder
        write_file(
            html.encode("utf-8", errors="xmlcharrefreplace"),
            self.print_page.file.abs_dest_path,
        )
예제 #16
0
    def on_post_build(self, config, **kwargs):
        """
        The post_build event does not alter any variables. Use this event to call post-build scripts.

        See https://www.mkdocs.org/user-guide/plugins/#on_post_build.
        """
        if not self.config.get("enabled"):
            return

        if len(self.context) == 0:
            msg = "Could not find a template context.\n"
            msg += "Report an issue at https://github.com/timvink/mkdocs-print-site-plugin\n"
            msg += f"And mention the template you're using: {get_theme_name(config)}"
            raise PluginError(msg)

        # Add print-site.js
        js_output_base_path = os.path.join(config["site_dir"], "js")
        js_file_path = os.path.join(js_output_base_path, "print-site.js")
        copy_file(os.path.join(os.path.join(HERE, "js"), "print-site.js"),
                  js_file_path)

        if self.config.get("include_css"):
            # Add print-site.css
            css_output_base_path = os.path.join(config["site_dir"], "css")
            css_file_path = os.path.join(css_output_base_path,
                                         "print-site.css")
            copy_file(
                os.path.join(os.path.join(HERE, "css"), "print-site.css"),
                css_file_path)

            # Add enumeration css
            for f in self.enum_css_files:
                f = f.replace("/", os.sep)
                css_file_path = os.path.join(config["site_dir"], f)
                copy_file(os.path.join(HERE, f), css_file_path)

            # Add theme CSS file
            css_file = "print-site-%s.css" % get_theme_name(config)
            if css_file in os.listdir(os.path.join(HERE, "css")):
                css_file_path = os.path.join(css_output_base_path, css_file)
                copy_file(os.path.join(os.path.join(HERE, "css"), css_file),
                          css_file_path)

        # Combine the HTML of all pages present in the navigation
        self.print_page.content = self.renderer.write_combined()
        # Generate a TOC sidebar for HTML version of print page
        self.print_page.toc = self.renderer.get_toc_sidebar()

        # Get the info for MkDocs to be able to apply a theme template on our print page
        env = config["theme"].get_env()
        # env.list_templates()
        template = env.get_template("main.html")
        self.context["page"] = self.print_page
        # Render the theme template for the print page
        html = template.render(self.context)

        # Remove lazy loading attributes from images
        # https://regex101.com/r/HVpKPs/1
        html = re.sub(r"(\<img.+)(loading=\"lazy\")", r"\1", html)

        # Compatiblity with mkdocs-chart-plugin
        # As this plugin adds some javascript to every page
        # It should be included in the print site also
        if config.get("plugins", {}).get("charts"):
            html = (config.get("plugins",
                               {}).get("charts").add_javascript_variables(
                                   html, self.print_page, config))

        # Compatibility with https://github.com/g-provost/lightgallery-markdown
        # This plugin insert link hrefs with double dashes, f.e.
        # <link href="//assets/css/somecss.css">
        # Details https://github.com/timvink/mkdocs-print-site-plugin/issues/68
        htmls = html.split("</head>")
        base_url = "../" if config.get("use_directory_urls") else ""
        htmls[0] = htmls[0].replace("href=\"//", f"href=\"{base_url}")
        htmls[0] = htmls[0].replace("src=\"//", f"src=\"{base_url}")
        html = "</head>".join(htmls)

        # Determine calls to required javascript functions
        js_calls = "remove_material_navigation();"
        js_calls += "remove_mkdocs_theme_navigation();"
        if self.config.get("add_table_of_contents"):
            js_calls += "generate_toc();"

        # Inject JS into print page
        print_site_js = ("""
        <script type="text/javascript">
        document.addEventListener('DOMContentLoaded', function () {
            %s
        })
        </script>
        """ % js_calls)
        html = html.replace("</head>", print_site_js + "</head>")

        # Write the print_page file to the output folder
        write_file(
            html.encode("utf-8", errors="xmlcharrefreplace"),
            self.print_page.file.abs_dest_path,
        )
예제 #17
0
    def on_post_build(self, config):
        """
        The post_build event does not alter any variables. Use this event to call post-build scripts.

        See https://www.mkdocs.org/user-guide/plugins/#on_post_build.
        """
        # Add print-site.js
        js_output_base_path = os.path.join(config["site_dir"], "js")
        js_file_path = os.path.join(js_output_base_path, "print-site.js")
        copy_file(os.path.join(os.path.join(HERE, "js"), "print-site.js"),
                  js_file_path)

        # Add print-site.css
        css_output_base_path = os.path.join(config["site_dir"], "css")
        css_file_path = os.path.join(css_output_base_path, "print-site.css")
        copy_file(os.path.join(os.path.join(HERE, "css"), "print-site.css"),
                  css_file_path)
        # Add theme CSS file
        css_file = "print-site-%s.css" % get_theme_name(config)
        if css_file in os.listdir(os.path.join(HERE, "css")):
            css_file_path = os.path.join(css_output_base_path, css_file)
            copy_file(os.path.join(os.path.join(HERE, "css"), css_file),
                      css_file_path)

        # Determine calls to required javascript functions
        js_calls = ""
        if self.config.get("add_table_of_contents"):
            js_calls += "generate_toc();"

        # Add JS file for compatibility for mkdocs-material instant loading
        # note this is inserted to all mkdocs pages,
        # because each page can be the start of instant loading session
        js_instant_loading = ("""
         // Subscribe functions for compatibility
         // with mkdocs-material's instant loading feature
                    
         if (
            typeof app !== "undefined" &&
            typeof app.document$ !== "undefined"
            ) {
            app.document$.subscribe(function() {
                if ( document.querySelector("#print-site-page") !== null ) {
                    %s
            }
            })
         }
        """ % js_calls)
        write_file(
            js_instant_loading.encode("utf-8", errors="xmlcharrefreplace"),
            os.path.join(js_output_base_path, "print-site-instant-loading.js"),
        )

        # Combine the HTML of all pages present in the navigation
        self.print_page.content = self.renderer.write_combined()

        # Get the info for MkDocs to be able to apply a theme template on our print page
        env = config["theme"].get_env()
        template = env.get_template("main.html")
        self.context["page"] = self.print_page
        # Render the theme template for the print page
        html = template.render(self.context)

        # Inject JS into print page
        print_site_js = ("""
        <script type="text/javascript">
        window.addEventListener('load', function () {
            %s
        })
        </script>
        """ % js_calls)
        html = html.replace("</body>", print_site_js + "</body>")

        # Write the print_page file to the output folder
        write_file(
            html.encode("utf-8", errors="xmlcharrefreplace"),
            self.print_page.file.abs_dest_path,
        )