Exemple #1
0
    def __call__(self, match):
        url = match.groups()[0]
        scheme, netloc, path, query, query, fragment = urlparse(url)

        if (scheme or netloc or not utils.is_markdown_file(path)):
            # Ignore URLs unless they are a relative link to a markdown file.
            return 'a href="%s"' % url

        if self.nav:
            # If the site navigation has been provided, then validate
            # the internal hyperlink, making sure the target actually exists.
            target_file = self.nav.file_context.make_absolute(path)
            if target_file not in self.nav.source_files:
                source_file = self.nav.file_context.current_file
                msg = (
                    'The page "%s" contained a hyperlink to "%s" which '
                    'is not listed in the "pages" configuration.'
                )
                assert False, msg % (source_file, target_file)
            path = utils.get_url_path(target_file)
            path = self.nav.url_context.make_relative(path)
        else:
            path = utils.get_url_path(path).lstrip('/')

        # Convert the .md hyperlink to a relative hyperlink to the HTML page.
        url = urlunparse((scheme, netloc, path, query, query, fragment))
        return 'a href="%s"' % url
Exemple #2
0
def path_to_url(url, nav):
    scheme, netloc, path, query, query, fragment = urlparse(url)

    if scheme or netloc or not path:
        # Ignore URLs unless they are a relative link to a markdown file.
        return url

    if nav and not utils.is_markdown_file(path):
        path = utils.create_media_urls(nav, [path])[0]
    elif nav:
        # If the site navigation has been provided, then validate
        # the internal hyperlink, making sure the target actually exists.
        target_file = nav.file_context.make_absolute(path)
        if target_file not in nav.source_files:
            source_file = nav.file_context.current_file
            msg = (
                'The page "%s" contained a hyperlink to "%s" which '
                'is not listed in the "pages" configuration.'
            )
            assert False, msg % (source_file, target_file)
        path = utils.get_url_path(target_file, nav.use_directory_urls)
        path = nav.url_context.make_relative(path)
    else:
        path = utils.get_url_path(path).lstrip('/')

    # Convert the .md hyperlink to a relative hyperlink to the HTML page.
    url = urlunparse((scheme, netloc, path, query, query, fragment))
    return url
Exemple #3
0
def path_to_url(url, nav, strict):
    scheme, netloc, path, query, query, fragment = urlparse(url)

    if scheme or netloc or not path:
        # Ignore URLs unless they are a relative link to a markdown file.
        return url

    if nav and not utils.is_markdown_file(path):
        path = utils.create_relative_media_url(nav, path)
    elif nav:
        # If the site navigation has been provided, then validate
        # the internal hyperlink, making sure the target actually exists.
        target_file = nav.file_context.make_absolute(path)
        if target_file not in nav.source_files:
            source_file = nav.file_context.current_file
            msg = (
                'The page "%s" contained a hyperlink to "%s" which '
                'is not listed in the "pages" configuration.'
            ) % (source_file, target_file)

            # In strict mode raise an error at this point.
            if strict:
                raise MarkdownNotFound(msg)
            # Otherwise, when strict mode isn't enabled, print out a warning
            # to the user and leave the URL as it is.
            #print(msg)
            #return url
        path = utils.get_url_path(target_file, nav.use_directory_urls)
        path = nav.url_context.make_relative(path)
    else:
        path = utils.get_url_path(path).lstrip('/')

    # Convert the .md hyperlink to a relative hyperlink to the HTML page.
    url = urlunparse((scheme, netloc, path, query, query, fragment))
    return url
def path_to_url(url, nav):
    scheme, netloc, path, query, query, fragment = urlparse(url)

    if scheme or netloc or not path:
        # Ignore URLs unless they are a relative link to a markdown file.
        return url

    if nav and not utils.is_markdown_file(path):
        path = utils.create_media_urls(nav, [path])[0]
    elif nav:
        # If the site navigation has been provided, then validate
        # the internal hyperlink, making sure the target actually exists.
        target_file = nav.file_context.make_absolute(path)
        if target_file not in nav.source_files:
            source_file = nav.file_context.current_file
            msg = ('The page "%s" contained a hyperlink to "%s" which '
                   'is not listed in the "pages" configuration.')
            assert False, msg % (source_file, target_file)
        path = utils.get_url_path(target_file, nav.use_directory_urls)
        path = nav.url_context.make_relative(path)
    else:
        path = utils.get_url_path(path).lstrip('/')

    # Convert the .md hyperlink to a relative hyperlink to the HTML page.
    url = urlunparse((scheme, netloc, path, query, query, fragment))
    return url
Exemple #5
0
 def do_GET(self):
     """
     The SimpleHTTPRequestHandler isn't designed to work with query strings.
     Everything we do with the query string is handle on the client-side, so
     throw it away here.
     """
     scheme, netloc, path, query, query, fragment = urlparse(self.path)
     if query is not '':
         self.path = urlunparse((scheme, netloc, path, '', '', fragment))
     return httpserver.SimpleHTTPRequestHandler.do_GET(self)
def create_media_urls(nav, url_list):
    """
    Return a list of URLs that have been processed correctly for inclusion in a page.
    """
    final_urls = []
    for url in url_list:
        # Allow links to fully qualified URL's
        parsed = urlparse(url)
        if parsed.netloc:
            final_urls.append(url)
        else:
            relative_url = '%s/%s' % (nav.url_context.make_relative('/'), url)
            final_urls.append(relative_url)
    return final_urls
Exemple #7
0
def create_media_urls(nav, url_list):
    """
    Return a list of URLs that have been processed correctly for inclusion in a page.
    """
    final_urls = []
    for url in url_list:
        # Allow links to fully qualified URL's
        parsed = urlparse(url)
        if parsed.netloc:
            final_urls.append(url)
        else:
            relative_url = '%s/%s' % (nav.url_context.make_relative('/'), url)
            final_urls.append(relative_url)
    return final_urls
Exemple #8
0
def create_media_urls(nav, path_list):
    """
    Return a list of URLs that have been processed correctly for inclusion in
    a page.
    """
    final_urls = []

    for path in path_list:
        # Allow links to fully qualified URL's
        parsed = urlparse(path)
        if parsed.netloc:
            final_urls.append(path)
            continue
        # We must be looking at a local path.
        url = path_to_url(path)
        relative_url = '%s/%s' % (nav.url_context.make_relative('/'), url)
        final_urls.append(relative_url)

    return final_urls
Exemple #9
0
def create_media_urls(nav, path_list):
    """
    Return a list of URLs that have been processed correctly for inclusion in
    a page.
    """
    final_urls = []

    for path in path_list:
        # Allow links to fully qualified URL's
        parsed = urlparse(path)
        if parsed.netloc:
            final_urls.append(path)
            continue
        # We must be looking at a local path.
        url = path_to_url(path)
        relative_url = '%s/%s' % (nav.url_context.make_relative('/'), url)
        final_urls.append(relative_url)

    return final_urls
Exemple #10
0
def create_relative_media_url(nav, url):
    """
    For a current page, create a relative url based on the given URL.

    On index.md (which becomes /index.html):
        image.png -> ./image.png
        /image.png -> ./image.png

    on sub/page.md (which becomes /sub/page/index.html):
        image.png -> ../image.png
        /image.png -> ../../image.png

    """

    # Allow links to fully qualified URL's
    parsed = urlparse(url)
    if parsed.netloc:
        return url

    # If the URL we are looking at starts with a /, then it should be
    # considered as absolute and will be 'relative' to the root.
    if url.startswith('/'):
        base = '/'
        url = url[1:]
    else:
        base = nav.url_context.base_path

    relative_url = '%s/%s' % (nav.url_context.make_relative(base), url)

    # TODO: Fix this, this is a hack. Relative urls are not being calculated
    # correctly for images in the same directory as the markdown. I think this
    # is due to us moving it into a directory with index.html, but I'm not sure
    if nav.url_context.base_path is not '/' and relative_url.startswith("./"):
        relative_url = ".%s" % relative_url

    return relative_url
Exemple #11
0
def create_relative_media_url(nav, url):
    """
    For a current page, create a relative url based on the given URL.

    On index.md (which becomes /index.html):
        image.png -> ./image.png
        /image.png -> ./image.png

    on sub/page.md (which becomes /sub/page/index.html):
        image.png -> ../image.png
        /image.png -> ../../image.png

    """

    # Allow links to fully qualified URL's
    parsed = urlparse(url)
    if parsed.netloc:
        return url

    # If the URL we are looking at starts with a /, then it should be
    # considered as absolute and will be 'relative' to the root.
    if url.startswith('/'):
        base = '/'
        url = url[1:]
    else:
        base = nav.url_context.base_path

    relative_url = '%s/%s' % (nav.url_context.make_relative(base), url)

    # TODO: Fix this, this is a hack. Relative urls are not being calculated
    # correctly for images in the same directory as the markdown. I think this
    # is due to us moving it into a directory with index.html, but I'm not sure
    if nav.url_context.base_path is not '/' and relative_url.startswith("./"):
        relative_url = ".%s" % relative_url

    return relative_url
Exemple #12
0
def validate_config(user_config):
    config = DEFAULT_CONFIG.copy()

    theme_in_config = 'theme' in user_config

    config.update(user_config)

    if not config['site_name']:
        raise ConfigurationError("Config must contain 'site_name' setting.")

    # Validate that the docs_dir and site_dir don't contain the
    # other as this will lead to copying back and forth on each
    # and eventually make a deep nested mess.
    abs_site_dir = os.path.abspath(config['site_dir'])
    abs_docs_dir = os.path.abspath(config['docs_dir'])
    if abs_docs_dir.startswith(abs_site_dir):
        raise ConfigurationError(
            "The 'docs_dir' can't be within the 'site_dir'.")
    elif abs_site_dir.startswith(abs_docs_dir):
        raise ConfigurationError(
            "The 'site_dir' can't be within the 'docs_dir'.")

    # If not specified, then the 'pages' config simply includes all
    # markdown files in the docs dir, without generating any header items
    # for them.
    pages = []
    extra_css = []
    extra_javascript = []
    for (dirpath, dirnames, filenames) in os.walk(config['docs_dir']):
        for filename in sorted(filenames):
            fullpath = os.path.join(dirpath, filename)
            relpath = os.path.relpath(fullpath, config['docs_dir'])

            if utils.is_markdown_file(filename):
                # index pages should always be the first listed page.
                if os.path.splitext(relpath)[0] == 'index':
                    pages.insert(0, relpath)
                else:
                    pages.append(relpath)
            elif utils.is_css_file(filename):
                extra_css.append(relpath)
            elif utils.is_javascript_file(filename):
                extra_javascript.append(relpath)

    if config['pages'] is None:
        config['pages'] = pages

    if config['extra_css'] is None:
        config['extra_css'] = extra_css

    if config['extra_javascript'] is None:
        config['extra_javascript'] = extra_javascript

    package_dir = os.path.dirname(__file__)
    theme_dir = [os.path.join(package_dir, 'themes', config['theme'])]

    if config['theme_dir'] is not None:
        # If the user has given us a custom theme but not a
        # builtin theme name then we don't want to merge them.
        if not theme_in_config:
            theme_dir = []
        theme_dir.insert(0, config['theme_dir'])

    config['theme_dir'] = theme_dir

    if config['repo_url'] is not None and config['repo_name'] is None:
        repo_host = urlparse(config['repo_url']).netloc.lower()
        if repo_host == 'github.com':
            config['repo_name'] = 'GitHub'
        elif repo_host == 'bitbucket.org':
            config['repo_name'] = 'Bitbucket'
        else:
            config['repo_name'] = repo_host.split('.')[0].title()

    if config['include_next_prev'] is None:
        config['include_next_prev'] = len(config['pages']) > 1

    if config['include_nav'] is None:
        config['include_nav'] = len(config['pages']) > 1

    # To Do:

    # The docs dir must exist.
    # The theme dir must exist.
    # Ensure 'theme' is one of 'mkdocs', 'readthedocs', 'custom'
    # A homepage 'index' must exist.
    # The theme 'base.html' file must exist.
    # Cannot set repo_name without setting repo_url.
    # Cannot set 'include_next_prev: true' when only one page exists.
    # Cannot set 'include_nav: true' when only one page exists.
    # Error if any config keys provided that are not in the DEFAULT_CONFIG.

    return config
Exemple #13
0
def validate_config(user_config):
    config = DEFAULT_CONFIG.copy()
    config.update(user_config)

    assert config['site_name'], "Config must contain 'site_name' setting."

    # If not specified, then the 'pages' config simply includes all
    # markdown files in the docs dir, without generating any header items
    # for them.
    pages = []
    extra_css = []
    extra_javascript = []
    for (dirpath, dirnames, filenames) in os.walk(config['docs_dir']):
        for filename in sorted(filenames):
            fullpath = os.path.join(dirpath, filename)
            relpath = os.path.relpath(fullpath, config['docs_dir'])

            if utils.is_markdown_file(filename):
                # index pages should always be the first listed page.
                if os.path.splitext(relpath)[0] == 'index':
                    pages.insert(0, relpath)
                else:
                    pages.append(relpath)
            elif utils.is_css_file(filename):
                extra_css.append(relpath)
            elif utils.is_javascript_file(filename):
                extra_javascript.append(relpath)

    if config['pages'] is None:
        config['pages'] = pages

    if config['extra_css'] is None:
        config['extra_css'] = extra_css

    if config['extra_javascript'] is None:
        config['extra_javascript'] = extra_javascript

    if config['theme_dir'] is None:
        package_dir = os.path.dirname(__file__)
        config['theme_dir'] = os.path.join(package_dir, 'themes',
                                           config['theme'])

    if config['repo_url'] is not None and config['repo_name'] is None:
        repo_host = urlparse(config['repo_url']).netloc.lower()
        if repo_host == 'github.com':
            config['repo_name'] = 'GitHub'
        elif repo_host == 'bitbucket.com':
            config['repo_name'] = 'Bitbucket'
        else:
            config['repo_name'] = repo_host.split('.')[0].title()

    if config['include_next_prev'] is None:
        config['include_next_prev'] = len(config['pages']) > 1

    if config['include_nav'] is None:
        config['include_nav'] = len(config['pages']) > 1

    # To Do:

    # The docs dir must exist.
    # The theme dir must exist.
    # Ensure 'theme' is one of 'mkdocs', 'readthedocs', 'custom'
    # A homepage 'index' must exist.
    # The theme 'base.html' file must exist.
    # Cannot set repo_name without setting repo_url.
    # Cannot set 'include_next_prev: true' when only one page exists.
    # Cannot set 'include_nav: true' when only one page exists.
    # Error if any config keys provided that are not in the DEFAULT_CONFIG.

    return config
Exemple #14
0
def validate_config(user_config):
    config = DEFAULT_CONFIG.copy()
    config.update(user_config)

    if not config['site_name']:
        sys.stderr.write("Config must contain 'site_name' setting.")
        sys.exit(errno.EINVAL)

    # If not specified, then the 'pages' config simply includes all
    # markdown files in the docs dir, without generating any header items
    # for them.
    pages = []
    extra_css = []
    extra_javascript = []
    for (dirpath, dirnames, filenames) in os.walk(config['docs_dir']):
        for filename in sorted(filenames):
            fullpath = os.path.join(dirpath, filename)
            relpath = os.path.relpath(fullpath, config['docs_dir'])

            if utils.is_markdown_file(filename):
                # index pages should always be the first listed page.
                if os.path.splitext(relpath)[0] == 'index':
                    pages.insert(0, relpath)
                else:
                    pages.append(relpath)
            elif utils.is_css_file(filename):
                extra_css.append(relpath)
            elif utils.is_javascript_file(filename):
                extra_javascript.append(relpath)

    if config['pages'] is None:
        config['pages'] = pages

    if config['extra_css'] is None:
        config['extra_css'] = extra_css

    if config['extra_javascript'] is None:
        config['extra_javascript'] = extra_javascript

    package_dir = os.path.dirname(__file__)
    theme_dir = [os.path.join(package_dir, 'themes', config['theme'])]

    if config['theme_dir'] is not None:
        theme_dir.insert(0, config['theme_dir'])

    config['theme_dir'] = theme_dir

    if config['repo_url'] is not None and config['repo_name'] is None:
        repo_host = urlparse(config['repo_url']).netloc.lower()
        if repo_host == 'github.com':
            config['repo_name'] = 'GitHub'
        elif repo_host == 'bitbucket.com':
            config['repo_name'] = 'Bitbucket'
        else:
            config['repo_name'] = repo_host.split('.')[0].title()

    if config['include_next_prev'] is None:
        config['include_next_prev'] = len(config['pages']) > 1

    if config['include_nav'] is None:
        config['include_nav'] = len(config['pages']) > 1

    # To Do:

    # The docs dir must exist.
    # The theme dir must exist.
    # Ensure 'theme' is one of 'mkdocs', 'readthedocs', 'custom'
    # A homepage 'index' must exist.
    # The theme 'base.html' file must exist.
    # Cannot set repo_name without setting repo_url.
    # Cannot set 'include_next_prev: true' when only one page exists.
    # Cannot set 'include_nav: true' when only one page exists.
    # Error if any config keys provided that are not in the DEFAULT_CONFIG.

    return config
Exemple #15
0
def validate_config(user_config):
    config = DEFAULT_CONFIG.copy()

    theme_in_config = 'theme' in user_config

    config.update(user_config)

    if not config['site_name']:
        raise ConfigurationError("Config must contain 'site_name' setting.")

    # Validate that the docs_dir and site_dir don't contain the
    # other as this will lead to copying back and forth on each
    # and eventually make a deep nested mess.
    abs_site_dir = os.path.abspath(config['site_dir'])
    abs_docs_dir = os.path.abspath(config['docs_dir'])
    if abs_docs_dir.startswith(abs_site_dir):
        raise ConfigurationError(
            "The 'docs_dir' can't be within the 'site_dir'.")
    elif abs_site_dir.startswith(abs_docs_dir):
        raise ConfigurationError(
            "The 'site_dir' can't be within the 'docs_dir'.")

    # If not specified, then the 'pages' config simply includes all
    # markdown files in the docs dir, without generating any header items
    # for them.
    pages = []
    extra_css = []
    extra_javascript = []
    for (dirpath, dirnames, filenames) in os.walk(config['docs_dir']):
        for filename in sorted(filenames):
            fullpath = os.path.join(dirpath, filename)
            relpath = os.path.relpath(fullpath, config['docs_dir'])

            if utils.is_markdown_file(filename):
                # index pages should always be the first listed page.
                if os.path.splitext(relpath)[0] == 'index':
                    pages.insert(0, relpath)
                else:
                    pages.append(relpath)
            elif utils.is_css_file(filename):
                extra_css.append(relpath)
            elif utils.is_javascript_file(filename):
                extra_javascript.append(relpath)

    if config['pages'] is None:
        config['pages'] = pages

    if config['extra_css'] is None:
        config['extra_css'] = extra_css

    if config['extra_javascript'] is None:
        config['extra_javascript'] = extra_javascript

    package_dir = os.path.dirname(__file__)
    theme_dir = [os.path.join(package_dir, 'themes', config['theme'])]

    if config['theme_dir'] is not None:
        # If the user has given us a custom theme but not a
        # builtin theme name then we don't want to merge them.
        if not theme_in_config:
            theme_dir = []
        theme_dir.insert(0, config['theme_dir'])

    config['theme_dir'] = theme_dir

    if config['repo_url'] is not None and config['repo_name'] is None:
        repo_host = urlparse(config['repo_url']).netloc.lower()
        if repo_host == 'github.com':
            config['repo_name'] = 'GitHub'
        elif repo_host == 'bitbucket.org':
            config['repo_name'] = 'Bitbucket'
        else:
            config['repo_name'] = repo_host.split('.')[0].title()

    if config['include_next_prev'] is None:
        config['include_next_prev'] = len(config['pages']) > 1

    if config['include_nav'] is None:
        config['include_nav'] = len(config['pages']) > 1

    # To Do:

    # The docs dir must exist.
    # The theme dir must exist.
    # Ensure 'theme' is one of 'mkdocs', 'readthedocs', 'custom'
    # A homepage 'index' must exist.
    # The theme 'base.html' file must exist.
    # Cannot set repo_name without setting repo_url.
    # Cannot set 'include_next_prev: true' when only one page exists.
    # Cannot set 'include_nav: true' when only one page exists.
    # Error if any config keys provided that are not in the DEFAULT_CONFIG.

    return config
Exemple #16
0
def validate_config(user_config):
    config = DEFAULT_CONFIG.copy()
    config.update(user_config)

    assert config["site_name"], "Config must contain 'site_name' setting."

    # If not specified, then the 'pages' config simply includes all
    # markdown files in the docs dir, without generating any header items
    # for them.
    pages = []
    extra_css = []
    extra_javascript = []
    for (dirpath, dirnames, filenames) in os.walk(config["docs_dir"]):
        for filename in sorted(filenames):
            fullpath = os.path.join(dirpath, filename)
            relpath = os.path.relpath(fullpath, config["docs_dir"])

            if utils.is_markdown_file(filename):
                # index pages should always be the first listed page.
                if os.path.splitext(relpath)[0] == "index":
                    pages.insert(0, relpath)
                else:
                    pages.append(relpath)
            elif utils.is_css_file(filename):
                extra_css.append(relpath)
            elif utils.is_javascript_file(filename):
                extra_javascript.append(relpath)

    if config["pages"] is None:
        config["pages"] = pages

    if config["extra_css"] is None:
        config["extra_css"] = extra_css

    if config["extra_javascript"] is None:
        config["extra_javascript"] = extra_javascript

    if config["theme_dir"] is None:
        package_dir = os.path.dirname(__file__)
        config["theme_dir"] = os.path.join(package_dir, "themes", config["theme"])

    if config["repo_url"] is not None and config["repo_name"] is None:
        repo_host = urlparse(config["repo_url"]).netloc.lower()
        if repo_host == "github.com":
            config["repo_name"] = "GitHub"
        elif repo_host == "bitbucket.com":
            config["repo_name"] = "Bitbucket"
        else:
            config["repo_name"] = repo_host.split(".")[0].title()

    if config["include_next_prev"] is None:
        config["include_next_prev"] = len(config["pages"]) > 1

    if config["include_nav"] is None:
        config["include_nav"] = len(config["pages"]) > 1

    # To Do:

    # The docs dir must exist.
    # The theme dir must exist.
    # Ensure 'theme' is one of 'mkdocs', 'readthedocs', 'custom'
    # A homepage 'index' must exist.
    # The theme 'base.html' file must exist.
    # Cannot set repo_name without setting repo_url.
    # Cannot set 'include_next_prev: true' when only one page exists.
    # Cannot set 'include_nav: true' when only one page exists.
    # Error if any config keys provided that are not in the DEFAULT_CONFIG.

    return config