#!/usr/bin/env python3

import argparse
import datetime
import logging
import os
import shutil
import subprocess
import sys
import time

import jinja2
import livereload
import markdown.util

import nav  # monkey patches mkdocs

from mkdocs import config
from mkdocs import exceptions
import mkdocs.commands.build

import amp
import blog
import mdx_clickhouse
import redirects
import single_page
import test
import util
import website


class ClickHouseMarkdown(markdown.extensions.Extension):
    class ClickHousePreprocessor(markdown.util.Processor):
        def run(self, lines):
            for line in lines:
                if '<!--hide-->' not in line:
                    yield line

    def extendMarkdown(self, md):
        md.preprocessors.register(self.ClickHousePreprocessor(), 'clickhouse_preprocessor', 31)


markdown.extensions.ClickHouseMarkdown = ClickHouseMarkdown


def build_for_lang(lang, args):
    logging.info(f'Building {lang} docs')
    os.environ['SINGLE_PAGE'] = '0'

    config_path = os.path.join(args.docs_dir, f'toc_{lang}.yml')
    if args.is_stable_release and not os.path.exists(config_path):
        logging.warning(f'Skipping {lang} docs, because {config} does not exist')
        return

    try:
        theme_cfg = {
            'name': None,
            'custom_dir': os.path.join(os.path.dirname(__file__), '..', args.theme_dir),
            'language': lang,
            'direction': 'rtl' if lang == 'fa' else 'ltr',
            'static_templates': ['404.html'],
            'extra': {
                'now': int(time.mktime(datetime.datetime.now().timetuple()))  # TODO better way to avoid caching
            }
        }

        # the following list of languages is sorted according to
        # https://en.wikipedia.org/wiki/List_of_languages_by_total_number_of_speakers
        languages = {
            'en': 'English',
            'zh': '中文',
            'es': 'Español',
            'fr': 'Français',
            'ru': 'Русский',
            'ja': '日本語',
            'tr': 'Türkçe',
            'fa': 'فارسی'
        }

        site_names = {
            'en': 'ClickHouse %s Documentation',
            'zh': 'ClickHouse文档 %s',
            'es': 'Documentación de ClickHouse %s',
            'fr': 'Documentation ClickHouse %s',
            'ru': 'Документация ClickHouse %s',
            'ja': 'ClickHouseドキュメント %s',
            'tr': 'ClickHouse Belgeleri %s',
            'fa': 'مستندات %sClickHouse'
        }

        assert len(site_names) == len(languages)

        if args.version_prefix:
            site_dir = os.path.join(args.docs_output_dir, args.version_prefix, lang)
        else:
            site_dir = os.path.join(args.docs_output_dir, lang)

        plugins = ['macros']
        if args.htmlproofer:
            plugins.append('htmlproofer')

        website_url = 'https://clickhouse.tech'
        site_name = site_names.get(lang, site_names['en']) % args.version_prefix
        site_name = site_name.replace('  ', ' ')
        raw_config = dict(
            site_name=site_name,
            site_url=f'{website_url}/docs/{lang}/',
            docs_dir=os.path.join(args.docs_dir, lang),
            site_dir=site_dir,
            strict=not args.version_prefix,
            theme=theme_cfg,
            copyright='©2016–2020 Yandex LLC',
            use_directory_urls=True,
            repo_name='ClickHouse/ClickHouse',
            repo_url='https://github.com/ClickHouse/ClickHouse/',
            edit_uri=f'edit/master/docs/{lang}',
            markdown_extensions=mdx_clickhouse.MARKDOWN_EXTENSIONS,
            plugins=plugins,
            extra=dict(
                now=datetime.datetime.now().isoformat(),
                stable_releases=args.stable_releases,
                version_prefix=args.version_prefix,
                single_page=False,
                rev=args.rev,
                rev_short=args.rev_short,
                rev_url=args.rev_url,
                website_url=website_url,
                events=args.events,
                languages=languages,
                includes_dir=os.path.join(os.path.dirname(__file__), '..', '_includes'),
                is_amp=False,
                is_blog=False
            )
        )

        if os.path.exists(config_path):
            raw_config['config_file'] = config_path
        else:
            raw_config['nav'] = nav.build_docs_nav(lang, args)

        cfg = config.load_config(**raw_config)

        if not args.skip_multi_page:
            try:
                mkdocs.commands.build.build(cfg)
            except jinja2.exceptions.TemplateError:
                if not args.version_prefix:
                    raise
                mdx_clickhouse.PatchedMacrosPlugin.disabled = True
                mkdocs.commands.build.build(cfg)

        if not (args.skip_amp or args.version_prefix):
            amp.build_amp(lang, args, cfg)

        if not args.skip_single_page:
            single_page.build_single_page_version(lang, args, raw_config.get('nav'), cfg)

        mdx_clickhouse.PatchedMacrosPlugin.disabled = False

        logging.info(f'Finished building {lang} docs')

    except exceptions.ConfigurationError as e:
        raise SystemExit('\n' + str(e))


def build_docs(args):
    tasks = []
    for lang in args.lang.split(','):
        if lang:
            tasks.append((lang, args,))
    util.run_function_in_parallel(build_for_lang, tasks, threads=False)
    if not args.version_prefix:
        redirects.build_docs_redirects(args)


def build(args):
    if os.path.exists(args.output_dir):
        shutil.rmtree(args.output_dir)

    if not args.skip_website:
        website.build_website(args)

    test.test_templates(args.website_dir)

    build_docs(args)

    from github import build_releases
    build_releases(args, build_docs)

    if not args.skip_blog:
        blog.build_blog(args)

    if not args.skip_website:
        website.process_benchmark_results(args)
        website.minify_website(args)
        redirects.build_static_redirects(args)


if __name__ == '__main__':
    os.chdir(os.path.join(os.path.dirname(__file__), '..'))
    website_dir = os.path.join('..', 'website')
    arg_parser = argparse.ArgumentParser()
    arg_parser.add_argument('--lang', default='en,es,fr,ru,zh,ja,tr,fa')
    arg_parser.add_argument('--blog-lang', default='en,ru')
    arg_parser.add_argument('--docs-dir', default='.')
    arg_parser.add_argument('--theme-dir', default=website_dir)
    arg_parser.add_argument('--website-dir', default=website_dir)
    arg_parser.add_argument('--blog-dir', default=os.path.join(website_dir, 'blog'))
    arg_parser.add_argument('--output-dir', default='build')
    arg_parser.add_argument('--enable-stable-releases', action='store_true')
    arg_parser.add_argument('--stable-releases-limit', type=int, default='3')
    arg_parser.add_argument('--lts-releases-limit', type=int, default='2')
    arg_parser.add_argument('--nav-limit', type=int, default='0')
    arg_parser.add_argument('--version-prefix', type=str, default='')
    arg_parser.add_argument('--is-stable-release', action='store_true')
    arg_parser.add_argument('--skip-multi-page', action='store_true')
    arg_parser.add_argument('--skip-single-page', action='store_true')
    arg_parser.add_argument('--skip-amp', action='store_true')
    arg_parser.add_argument('--skip-pdf', action='store_true')
    arg_parser.add_argument('--skip-website', action='store_true')
    arg_parser.add_argument('--skip-blog', action='store_true')
    arg_parser.add_argument('--skip-git-log', action='store_true')
    arg_parser.add_argument('--test-only', action='store_true')
    arg_parser.add_argument('--minify', action='store_true')
    arg_parser.add_argument('--htmlproofer', action='store_true')
    arg_parser.add_argument('--no-docs-macros', action='store_true')
    arg_parser.add_argument('--save-raw-single-page', type=str)
    arg_parser.add_argument('--livereload', type=int, default='0')
    arg_parser.add_argument('--verbose', action='store_true')

    args = arg_parser.parse_args()

    logging.basicConfig(
        level=logging.DEBUG if args.verbose else logging.INFO,
        stream=sys.stderr
    )

    logging.getLogger('MARKDOWN').setLevel(logging.INFO)

    args.docs_output_dir = os.path.join(os.path.abspath(args.output_dir), 'docs')
    args.blog_output_dir = os.path.join(os.path.abspath(args.output_dir), 'blog')

    from github import choose_latest_releases, get_events
    args.stable_releases = choose_latest_releases(args) if args.enable_stable_releases else []
    args.rev = subprocess.check_output('git rev-parse HEAD', shell=True).decode('utf-8').strip()
    args.rev_short = subprocess.check_output('git rev-parse --short HEAD', shell=True).decode('utf-8').strip()
    args.rev_url = f'https://github.com/ClickHouse/ClickHouse/commit/{args.rev}'
    args.events = get_events(args)

    if args.test_only:
        args.skip_multi_page = True
        args.skip_blog = True
        args.skip_website = True
        args.skip_pdf = True
        args.skip_amp = True

    if args.skip_git_log or args.skip_amp:
        mdx_clickhouse.PatchedMacrosPlugin.skip_git_log = True

    from build import build
    build(args)

    if args.livereload:
        new_args = [arg for arg in sys.argv if not arg.startswith('--livereload')]
        new_args = sys.executable + ' ' + ' '.join(new_args)

        server = livereload.Server()
        server.watch(args.docs_dir + '**/*', livereload.shell(new_args, cwd='tools', shell=True))
        server.watch(args.website_dir + '**/*', livereload.shell(new_args, cwd='tools', shell=True))
        server.serve(
            root=args.output_dir,
            host='0.0.0.0',
            port=args.livereload
        )
        sys.exit(0)

a287798b04345c2e7409e3f91490eaeb82e08c24
<mask token>


class ClickHouseMarkdown(markdown.extensions.Extension):


    class ClickHousePreprocessor(markdown.util.Processor):

        def run(self, lines):
            for line in lines:
                if '<!--hide-->' not in line:
                    yield line

    def extendMarkdown(self, md):
        md.preprocessors.register(self.ClickHousePreprocessor(),
            'clickhouse_preprocessor', 31)


<mask token>


def build_for_lang(lang, args):
    logging.info(f'Building {lang} docs')
    os.environ['SINGLE_PAGE'] = '0'
    config_path = os.path.join(args.docs_dir, f'toc_{lang}.yml')
    if args.is_stable_release and not os.path.exists(config_path):
        logging.warning(
            f'Skipping {lang} docs, because {config} does not exist')
        return
    try:
        theme_cfg = {'name': None, 'custom_dir': os.path.join(os.path.
            dirname(__file__), '..', args.theme_dir), 'language': lang,
            'direction': 'rtl' if lang == 'fa' else 'ltr',
            'static_templates': ['404.html'], 'extra': {'now': int(time.
            mktime(datetime.datetime.now().timetuple()))}}
        languages = {'en': 'English', 'zh': '中文', 'es': 'Español', 'fr':
            'Français', 'ru': 'Русский', 'ja': '日本語', 'tr': 'Türkçe', 'fa':
            'فارسی'}
        site_names = {'en': 'ClickHouse %s Documentation', 'zh':
            'ClickHouse文档 %s', 'es': 'Documentación de ClickHouse %s', 'fr':
            'Documentation ClickHouse %s', 'ru':
            'Документация ClickHouse %s', 'ja': 'ClickHouseドキュメント %s', 'tr':
            'ClickHouse Belgeleri %s', 'fa': 'مستندات %sClickHouse'}
        assert len(site_names) == len(languages)
        if args.version_prefix:
            site_dir = os.path.join(args.docs_output_dir, args.
                version_prefix, lang)
        else:
            site_dir = os.path.join(args.docs_output_dir, lang)
        plugins = ['macros']
        if args.htmlproofer:
            plugins.append('htmlproofer')
        website_url = 'https://clickhouse.tech'
        site_name = site_names.get(lang, site_names['en']
            ) % args.version_prefix
        site_name = site_name.replace('  ', ' ')
        raw_config = dict(site_name=site_name, site_url=
            f'{website_url}/docs/{lang}/', docs_dir=os.path.join(args.
            docs_dir, lang), site_dir=site_dir, strict=not args.
            version_prefix, theme=theme_cfg, copyright=
            '©2016–2020 Yandex LLC', use_directory_urls=True, repo_name=
            'ClickHouse/ClickHouse', repo_url=
            'https://github.com/ClickHouse/ClickHouse/', edit_uri=
            f'edit/master/docs/{lang}', markdown_extensions=mdx_clickhouse.
            MARKDOWN_EXTENSIONS, plugins=plugins, extra=dict(now=datetime.
            datetime.now().isoformat(), stable_releases=args.
            stable_releases, version_prefix=args.version_prefix,
            single_page=False, rev=args.rev, rev_short=args.rev_short,
            rev_url=args.rev_url, website_url=website_url, events=args.
            events, languages=languages, includes_dir=os.path.join(os.path.
            dirname(__file__), '..', '_includes'), is_amp=False, is_blog=False)
            )
        if os.path.exists(config_path):
            raw_config['config_file'] = config_path
        else:
            raw_config['nav'] = nav.build_docs_nav(lang, args)
        cfg = config.load_config(**raw_config)
        if not args.skip_multi_page:
            try:
                mkdocs.commands.build.build(cfg)
            except jinja2.exceptions.TemplateError:
                if not args.version_prefix:
                    raise
                mdx_clickhouse.PatchedMacrosPlugin.disabled = True
                mkdocs.commands.build.build(cfg)
        if not (args.skip_amp or args.version_prefix):
            amp.build_amp(lang, args, cfg)
        if not args.skip_single_page:
            single_page.build_single_page_version(lang, args, raw_config.
                get('nav'), cfg)
        mdx_clickhouse.PatchedMacrosPlugin.disabled = False
        logging.info(f'Finished building {lang} docs')
    except exceptions.ConfigurationError as e:
        raise SystemExit('\n' + str(e))


def build_docs(args):
    tasks = []
    for lang in args.lang.split(','):
        if lang:
            tasks.append((lang, args))
    util.run_function_in_parallel(build_for_lang, tasks, threads=False)
    if not args.version_prefix:
        redirects.build_docs_redirects(args)


def build(args):
    if os.path.exists(args.output_dir):
        shutil.rmtree(args.output_dir)
    if not args.skip_website:
        website.build_website(args)
    test.test_templates(args.website_dir)
    build_docs(args)
    from github import build_releases
    build_releases(args, build_docs)
    if not args.skip_blog:
        blog.build_blog(args)
    if not args.skip_website:
        website.process_benchmark_results(args)
        website.minify_website(args)
        redirects.build_static_redirects(args)


<mask token>

<mask token>


class ClickHouseMarkdown(markdown.extensions.Extension):


    class ClickHousePreprocessor(markdown.util.Processor):

        def run(self, lines):
            for line in lines:
                if '<!--hide-->' not in line:
                    yield line

    def extendMarkdown(self, md):
        md.preprocessors.register(self.ClickHousePreprocessor(),
            'clickhouse_preprocessor', 31)


<mask token>


def build_for_lang(lang, args):
    logging.info(f'Building {lang} docs')
    os.environ['SINGLE_PAGE'] = '0'
    config_path = os.path.join(args.docs_dir, f'toc_{lang}.yml')
    if args.is_stable_release and not os.path.exists(config_path):
        logging.warning(
            f'Skipping {lang} docs, because {config} does not exist')
        return
    try:
        theme_cfg = {'name': None, 'custom_dir': os.path.join(os.path.
            dirname(__file__), '..', args.theme_dir), 'language': lang,
            'direction': 'rtl' if lang == 'fa' else 'ltr',
            'static_templates': ['404.html'], 'extra': {'now': int(time.
            mktime(datetime.datetime.now().timetuple()))}}
        languages = {'en': 'English', 'zh': '中文', 'es': 'Español', 'fr':
            'Français', 'ru': 'Русский', 'ja': '日本語', 'tr': 'Türkçe', 'fa':
            'فارسی'}
        site_names = {'en': 'ClickHouse %s Documentation', 'zh':
            'ClickHouse文档 %s', 'es': 'Documentación de ClickHouse %s', 'fr':
            'Documentation ClickHouse %s', 'ru':
            'Документация ClickHouse %s', 'ja': 'ClickHouseドキュメント %s', 'tr':
            'ClickHouse Belgeleri %s', 'fa': 'مستندات %sClickHouse'}
        assert len(site_names) == len(languages)
        if args.version_prefix:
            site_dir = os.path.join(args.docs_output_dir, args.
                version_prefix, lang)
        else:
            site_dir = os.path.join(args.docs_output_dir, lang)
        plugins = ['macros']
        if args.htmlproofer:
            plugins.append('htmlproofer')
        website_url = 'https://clickhouse.tech'
        site_name = site_names.get(lang, site_names['en']
            ) % args.version_prefix
        site_name = site_name.replace('  ', ' ')
        raw_config = dict(site_name=site_name, site_url=
            f'{website_url}/docs/{lang}/', docs_dir=os.path.join(args.
            docs_dir, lang), site_dir=site_dir, strict=not args.
            version_prefix, theme=theme_cfg, copyright=
            '©2016–2020 Yandex LLC', use_directory_urls=True, repo_name=
            'ClickHouse/ClickHouse', repo_url=
            'https://github.com/ClickHouse/ClickHouse/', edit_uri=
            f'edit/master/docs/{lang}', markdown_extensions=mdx_clickhouse.
            MARKDOWN_EXTENSIONS, plugins=plugins, extra=dict(now=datetime.
            datetime.now().isoformat(), stable_releases=args.
            stable_releases, version_prefix=args.version_prefix,
            single_page=False, rev=args.rev, rev_short=args.rev_short,
            rev_url=args.rev_url, website_url=website_url, events=args.
            events, languages=languages, includes_dir=os.path.join(os.path.
            dirname(__file__), '..', '_includes'), is_amp=False, is_blog=False)
            )
        if os.path.exists(config_path):
            raw_config['config_file'] = config_path
        else:
            raw_config['nav'] = nav.build_docs_nav(lang, args)
        cfg = config.load_config(**raw_config)
        if not args.skip_multi_page:
            try:
                mkdocs.commands.build.build(cfg)
            except jinja2.exceptions.TemplateError:
                if not args.version_prefix:
                    raise
                mdx_clickhouse.PatchedMacrosPlugin.disabled = True
                mkdocs.commands.build.build(cfg)
        if not (args.skip_amp or args.version_prefix):
            amp.build_amp(lang, args, cfg)
        if not args.skip_single_page:
            single_page.build_single_page_version(lang, args, raw_config.
                get('nav'), cfg)
        mdx_clickhouse.PatchedMacrosPlugin.disabled = False
        logging.info(f'Finished building {lang} docs')
    except exceptions.ConfigurationError as e:
        raise SystemExit('\n' + str(e))


def build_docs(args):
    tasks = []
    for lang in args.lang.split(','):
        if lang:
            tasks.append((lang, args))
    util.run_function_in_parallel(build_for_lang, tasks, threads=False)
    if not args.version_prefix:
        redirects.build_docs_redirects(args)


def build(args):
    if os.path.exists(args.output_dir):
        shutil.rmtree(args.output_dir)
    if not args.skip_website:
        website.build_website(args)
    test.test_templates(args.website_dir)
    build_docs(args)
    from github import build_releases
    build_releases(args, build_docs)
    if not args.skip_blog:
        blog.build_blog(args)
    if not args.skip_website:
        website.process_benchmark_results(args)
        website.minify_website(args)
        redirects.build_static_redirects(args)


if __name__ == '__main__':
    os.chdir(os.path.join(os.path.dirname(__file__), '..'))
    website_dir = os.path.join('..', 'website')
    arg_parser = argparse.ArgumentParser()
    arg_parser.add_argument('--lang', default='en,es,fr,ru,zh,ja,tr,fa')
    arg_parser.add_argument('--blog-lang', default='en,ru')
    arg_parser.add_argument('--docs-dir', default='.')
    arg_parser.add_argument('--theme-dir', default=website_dir)
    arg_parser.add_argument('--website-dir', default=website_dir)
    arg_parser.add_argument('--blog-dir', default=os.path.join(website_dir,
        'blog'))
    arg_parser.add_argument('--output-dir', default='build')
    arg_parser.add_argument('--enable-stable-releases', action='store_true')
    arg_parser.add_argument('--stable-releases-limit', type=int, default='3')
    arg_parser.add_argument('--lts-releases-limit', type=int, default='2')
    arg_parser.add_argument('--nav-limit', type=int, default='0')
    arg_parser.add_argument('--version-prefix', type=str, default='')
    arg_parser.add_argument('--is-stable-release', action='store_true')
    arg_parser.add_argument('--skip-multi-page', action='store_true')
    arg_parser.add_argument('--skip-single-page', action='store_true')
    arg_parser.add_argument('--skip-amp', action='store_true')
    arg_parser.add_argument('--skip-pdf', action='store_true')
    arg_parser.add_argument('--skip-website', action='store_true')
    arg_parser.add_argument('--skip-blog', action='store_true')
    arg_parser.add_argument('--skip-git-log', action='store_true')
    arg_parser.add_argument('--test-only', action='store_true')
    arg_parser.add_argument('--minify', action='store_true')
    arg_parser.add_argument('--htmlproofer', action='store_true')
    arg_parser.add_argument('--no-docs-macros', action='store_true')
    arg_parser.add_argument('--save-raw-single-page', type=str)
    arg_parser.add_argument('--livereload', type=int, default='0')
    arg_parser.add_argument('--verbose', action='store_true')
    args = arg_parser.parse_args()
    logging.basicConfig(level=logging.DEBUG if args.verbose else logging.
        INFO, stream=sys.stderr)
    logging.getLogger('MARKDOWN').setLevel(logging.INFO)
    args.docs_output_dir = os.path.join(os.path.abspath(args.output_dir),
        'docs')
    args.blog_output_dir = os.path.join(os.path.abspath(args.output_dir),
        'blog')
    from github import choose_latest_releases, get_events
    args.stable_releases = choose_latest_releases(args
        ) if args.enable_stable_releases else []
    args.rev = subprocess.check_output('git rev-parse HEAD', shell=True
        ).decode('utf-8').strip()
    args.rev_short = subprocess.check_output('git rev-parse --short HEAD',
        shell=True).decode('utf-8').strip()
    args.rev_url = (
        f'https://github.com/ClickHouse/ClickHouse/commit/{args.rev}')
    args.events = get_events(args)
    if args.test_only:
        args.skip_multi_page = True
        args.skip_blog = True
        args.skip_website = True
        args.skip_pdf = True
        args.skip_amp = True
    if args.skip_git_log or args.skip_amp:
        mdx_clickhouse.PatchedMacrosPlugin.skip_git_log = True
    from build import build
    build(args)
    if args.livereload:
        new_args = [arg for arg in sys.argv if not arg.startswith(
            '--livereload')]
        new_args = sys.executable + ' ' + ' '.join(new_args)
        server = livereload.Server()
        server.watch(args.docs_dir + '**/*', livereload.shell(new_args, cwd
            ='tools', shell=True))
        server.watch(args.website_dir + '**/*', livereload.shell(new_args,
            cwd='tools', shell=True))
        server.serve(root=args.output_dir, host='0.0.0.0', port=args.livereload
            )
        sys.exit(0)

<mask token>


class ClickHouseMarkdown(markdown.extensions.Extension):


    class ClickHousePreprocessor(markdown.util.Processor):

        def run(self, lines):
            for line in lines:
                if '<!--hide-->' not in line:
                    yield line

    def extendMarkdown(self, md):
        md.preprocessors.register(self.ClickHousePreprocessor(),
            'clickhouse_preprocessor', 31)


markdown.extensions.ClickHouseMarkdown = ClickHouseMarkdown


def build_for_lang(lang, args):
    logging.info(f'Building {lang} docs')
    os.environ['SINGLE_PAGE'] = '0'
    config_path = os.path.join(args.docs_dir, f'toc_{lang}.yml')
    if args.is_stable_release and not os.path.exists(config_path):
        logging.warning(
            f'Skipping {lang} docs, because {config} does not exist')
        return
    try:
        theme_cfg = {'name': None, 'custom_dir': os.path.join(os.path.
            dirname(__file__), '..', args.theme_dir), 'language': lang,
            'direction': 'rtl' if lang == 'fa' else 'ltr',
            'static_templates': ['404.html'], 'extra': {'now': int(time.
            mktime(datetime.datetime.now().timetuple()))}}
        languages = {'en': 'English', 'zh': '中文', 'es': 'Español', 'fr':
            'Français', 'ru': 'Русский', 'ja': '日本語', 'tr': 'Türkçe', 'fa':
            'فارسی'}
        site_names = {'en': 'ClickHouse %s Documentation', 'zh':
            'ClickHouse文档 %s', 'es': 'Documentación de ClickHouse %s', 'fr':
            'Documentation ClickHouse %s', 'ru':
            'Документация ClickHouse %s', 'ja': 'ClickHouseドキュメント %s', 'tr':
            'ClickHouse Belgeleri %s', 'fa': 'مستندات %sClickHouse'}
        assert len(site_names) == len(languages)
        if args.version_prefix:
            site_dir = os.path.join(args.docs_output_dir, args.
                version_prefix, lang)
        else:
            site_dir = os.path.join(args.docs_output_dir, lang)
        plugins = ['macros']
        if args.htmlproofer:
            plugins.append('htmlproofer')
        website_url = 'https://clickhouse.tech'
        site_name = site_names.get(lang, site_names['en']
            ) % args.version_prefix
        site_name = site_name.replace('  ', ' ')
        raw_config = dict(site_name=site_name, site_url=
            f'{website_url}/docs/{lang}/', docs_dir=os.path.join(args.
            docs_dir, lang), site_dir=site_dir, strict=not args.
            version_prefix, theme=theme_cfg, copyright=
            '©2016–2020 Yandex LLC', use_directory_urls=True, repo_name=
            'ClickHouse/ClickHouse', repo_url=
            'https://github.com/ClickHouse/ClickHouse/', edit_uri=
            f'edit/master/docs/{lang}', markdown_extensions=mdx_clickhouse.
            MARKDOWN_EXTENSIONS, plugins=plugins, extra=dict(now=datetime.
            datetime.now().isoformat(), stable_releases=args.
            stable_releases, version_prefix=args.version_prefix,
            single_page=False, rev=args.rev, rev_short=args.rev_short,
            rev_url=args.rev_url, website_url=website_url, events=args.
            events, languages=languages, includes_dir=os.path.join(os.path.
            dirname(__file__), '..', '_includes'), is_amp=False, is_blog=False)
            )
        if os.path.exists(config_path):
            raw_config['config_file'] = config_path
        else:
            raw_config['nav'] = nav.build_docs_nav(lang, args)
        cfg = config.load_config(**raw_config)
        if not args.skip_multi_page:
            try:
                mkdocs.commands.build.build(cfg)
            except jinja2.exceptions.TemplateError:
                if not args.version_prefix:
                    raise
                mdx_clickhouse.PatchedMacrosPlugin.disabled = True
                mkdocs.commands.build.build(cfg)
        if not (args.skip_amp or args.version_prefix):
            amp.build_amp(lang, args, cfg)
        if not args.skip_single_page:
            single_page.build_single_page_version(lang, args, raw_config.
                get('nav'), cfg)
        mdx_clickhouse.PatchedMacrosPlugin.disabled = False
        logging.info(f'Finished building {lang} docs')
    except exceptions.ConfigurationError as e:
        raise SystemExit('\n' + str(e))


def build_docs(args):
    tasks = []
    for lang in args.lang.split(','):
        if lang:
            tasks.append((lang, args))
    util.run_function_in_parallel(build_for_lang, tasks, threads=False)
    if not args.version_prefix:
        redirects.build_docs_redirects(args)


def build(args):
    if os.path.exists(args.output_dir):
        shutil.rmtree(args.output_dir)
    if not args.skip_website:
        website.build_website(args)
    test.test_templates(args.website_dir)
    build_docs(args)
    from github import build_releases
    build_releases(args, build_docs)
    if not args.skip_blog:
        blog.build_blog(args)
    if not args.skip_website:
        website.process_benchmark_results(args)
        website.minify_website(args)
        redirects.build_static_redirects(args)


if __name__ == '__main__':
    os.chdir(os.path.join(os.path.dirname(__file__), '..'))
    website_dir = os.path.join('..', 'website')
    arg_parser = argparse.ArgumentParser()
    arg_parser.add_argument('--lang', default='en,es,fr,ru,zh,ja,tr,fa')
    arg_parser.add_argument('--blog-lang', default='en,ru')
    arg_parser.add_argument('--docs-dir', default='.')
    arg_parser.add_argument('--theme-dir', default=website_dir)
    arg_parser.add_argument('--website-dir', default=website_dir)
    arg_parser.add_argument('--blog-dir', default=os.path.join(website_dir,
        'blog'))
    arg_parser.add_argument('--output-dir', default='build')
    arg_parser.add_argument('--enable-stable-releases', action='store_true')
    arg_parser.add_argument('--stable-releases-limit', type=int, default='3')
    arg_parser.add_argument('--lts-releases-limit', type=int, default='2')
    arg_parser.add_argument('--nav-limit', type=int, default='0')
    arg_parser.add_argument('--version-prefix', type=str, default='')
    arg_parser.add_argument('--is-stable-release', action='store_true')
    arg_parser.add_argument('--skip-multi-page', action='store_true')
    arg_parser.add_argument('--skip-single-page', action='store_true')
    arg_parser.add_argument('--skip-amp', action='store_true')
    arg_parser.add_argument('--skip-pdf', action='store_true')
    arg_parser.add_argument('--skip-website', action='store_true')
    arg_parser.add_argument('--skip-blog', action='store_true')
    arg_parser.add_argument('--skip-git-log', action='store_true')
    arg_parser.add_argument('--test-only', action='store_true')
    arg_parser.add_argument('--minify', action='store_true')
    arg_parser.add_argument('--htmlproofer', action='store_true')
    arg_parser.add_argument('--no-docs-macros', action='store_true')
    arg_parser.add_argument('--save-raw-single-page', type=str)
    arg_parser.add_argument('--livereload', type=int, default='0')
    arg_parser.add_argument('--verbose', action='store_true')
    args = arg_parser.parse_args()
    logging.basicConfig(level=logging.DEBUG if args.verbose else logging.
        INFO, stream=sys.stderr)
    logging.getLogger('MARKDOWN').setLevel(logging.INFO)
    args.docs_output_dir = os.path.join(os.path.abspath(args.output_dir),
        'docs')
    args.blog_output_dir = os.path.join(os.path.abspath(args.output_dir),
        'blog')
    from github import choose_latest_releases, get_events
    args.stable_releases = choose_latest_releases(args
        ) if args.enable_stable_releases else []
    args.rev = subprocess.check_output('git rev-parse HEAD', shell=True
        ).decode('utf-8').strip()
    args.rev_short = subprocess.check_output('git rev-parse --short HEAD',
        shell=True).decode('utf-8').strip()
    args.rev_url = (
        f'https://github.com/ClickHouse/ClickHouse/commit/{args.rev}')
    args.events = get_events(args)
    if args.test_only:
        args.skip_multi_page = True
        args.skip_blog = True
        args.skip_website = True
        args.skip_pdf = True
        args.skip_amp = True
    if args.skip_git_log or args.skip_amp:
        mdx_clickhouse.PatchedMacrosPlugin.skip_git_log = True
    from build import build
    build(args)
    if args.livereload:
        new_args = [arg for arg in sys.argv if not arg.startswith(
            '--livereload')]
        new_args = sys.executable + ' ' + ' '.join(new_args)
        server = livereload.Server()
        server.watch(args.docs_dir + '**/*', livereload.shell(new_args, cwd
            ='tools', shell=True))
        server.watch(args.website_dir + '**/*', livereload.shell(new_args,
            cwd='tools', shell=True))
        server.serve(root=args.output_dir, host='0.0.0.0', port=args.livereload
            )
        sys.exit(0)

import argparse
import datetime
import logging
import os
import shutil
import subprocess
import sys
import time
import jinja2
import livereload
import markdown.util
import nav
from mkdocs import config
from mkdocs import exceptions
import mkdocs.commands.build
import amp
import blog
import mdx_clickhouse
import redirects
import single_page
import test
import util
import website


class ClickHouseMarkdown(markdown.extensions.Extension):


    class ClickHousePreprocessor(markdown.util.Processor):

        def run(self, lines):
            for line in lines:
                if '<!--hide-->' not in line:
                    yield line

    def extendMarkdown(self, md):
        md.preprocessors.register(self.ClickHousePreprocessor(),
            'clickhouse_preprocessor', 31)


markdown.extensions.ClickHouseMarkdown = ClickHouseMarkdown


def build_for_lang(lang, args):
    logging.info(f'Building {lang} docs')
    os.environ['SINGLE_PAGE'] = '0'
    config_path = os.path.join(args.docs_dir, f'toc_{lang}.yml')
    if args.is_stable_release and not os.path.exists(config_path):
        logging.warning(
            f'Skipping {lang} docs, because {config} does not exist')
        return
    try:
        theme_cfg = {'name': None, 'custom_dir': os.path.join(os.path.
            dirname(__file__), '..', args.theme_dir), 'language': lang,
            'direction': 'rtl' if lang == 'fa' else 'ltr',
            'static_templates': ['404.html'], 'extra': {'now': int(time.
            mktime(datetime.datetime.now().timetuple()))}}
        languages = {'en': 'English', 'zh': '中文', 'es': 'Español', 'fr':
            'Français', 'ru': 'Русский', 'ja': '日本語', 'tr': 'Türkçe', 'fa':
            'فارسی'}
        site_names = {'en': 'ClickHouse %s Documentation', 'zh':
            'ClickHouse文档 %s', 'es': 'Documentación de ClickHouse %s', 'fr':
            'Documentation ClickHouse %s', 'ru':
            'Документация ClickHouse %s', 'ja': 'ClickHouseドキュメント %s', 'tr':
            'ClickHouse Belgeleri %s', 'fa': 'مستندات %sClickHouse'}
        assert len(site_names) == len(languages)
        if args.version_prefix:
            site_dir = os.path.join(args.docs_output_dir, args.
                version_prefix, lang)
        else:
            site_dir = os.path.join(args.docs_output_dir, lang)
        plugins = ['macros']
        if args.htmlproofer:
            plugins.append('htmlproofer')
        website_url = 'https://clickhouse.tech'
        site_name = site_names.get(lang, site_names['en']
            ) % args.version_prefix
        site_name = site_name.replace('  ', ' ')
        raw_config = dict(site_name=site_name, site_url=
            f'{website_url}/docs/{lang}/', docs_dir=os.path.join(args.
            docs_dir, lang), site_dir=site_dir, strict=not args.
            version_prefix, theme=theme_cfg, copyright=
            '©2016–2020 Yandex LLC', use_directory_urls=True, repo_name=
            'ClickHouse/ClickHouse', repo_url=
            'https://github.com/ClickHouse/ClickHouse/', edit_uri=
            f'edit/master/docs/{lang}', markdown_extensions=mdx_clickhouse.
            MARKDOWN_EXTENSIONS, plugins=plugins, extra=dict(now=datetime.
            datetime.now().isoformat(), stable_releases=args.
            stable_releases, version_prefix=args.version_prefix,
            single_page=False, rev=args.rev, rev_short=args.rev_short,
            rev_url=args.rev_url, website_url=website_url, events=args.
            events, languages=languages, includes_dir=os.path.join(os.path.
            dirname(__file__), '..', '_includes'), is_amp=False, is_blog=False)
            )
        if os.path.exists(config_path):
            raw_config['config_file'] = config_path
        else:
            raw_config['nav'] = nav.build_docs_nav(lang, args)
        cfg = config.load_config(**raw_config)
        if not args.skip_multi_page:
            try:
                mkdocs.commands.build.build(cfg)
            except jinja2.exceptions.TemplateError:
                if not args.version_prefix:
                    raise
                mdx_clickhouse.PatchedMacrosPlugin.disabled = True
                mkdocs.commands.build.build(cfg)
        if not (args.skip_amp or args.version_prefix):
            amp.build_amp(lang, args, cfg)
        if not args.skip_single_page:
            single_page.build_single_page_version(lang, args, raw_config.
                get('nav'), cfg)
        mdx_clickhouse.PatchedMacrosPlugin.disabled = False
        logging.info(f'Finished building {lang} docs')
    except exceptions.ConfigurationError as e:
        raise SystemExit('\n' + str(e))


def build_docs(args):
    tasks = []
    for lang in args.lang.split(','):
        if lang:
            tasks.append((lang, args))
    util.run_function_in_parallel(build_for_lang, tasks, threads=False)
    if not args.version_prefix:
        redirects.build_docs_redirects(args)


def build(args):
    if os.path.exists(args.output_dir):
        shutil.rmtree(args.output_dir)
    if not args.skip_website:
        website.build_website(args)
    test.test_templates(args.website_dir)
    build_docs(args)
    from github import build_releases
    build_releases(args, build_docs)
    if not args.skip_blog:
        blog.build_blog(args)
    if not args.skip_website:
        website.process_benchmark_results(args)
        website.minify_website(args)
        redirects.build_static_redirects(args)


if __name__ == '__main__':
    os.chdir(os.path.join(os.path.dirname(__file__), '..'))
    website_dir = os.path.join('..', 'website')
    arg_parser = argparse.ArgumentParser()
    arg_parser.add_argument('--lang', default='en,es,fr,ru,zh,ja,tr,fa')
    arg_parser.add_argument('--blog-lang', default='en,ru')
    arg_parser.add_argument('--docs-dir', default='.')
    arg_parser.add_argument('--theme-dir', default=website_dir)
    arg_parser.add_argument('--website-dir', default=website_dir)
    arg_parser.add_argument('--blog-dir', default=os.path.join(website_dir,
        'blog'))
    arg_parser.add_argument('--output-dir', default='build')
    arg_parser.add_argument('--enable-stable-releases', action='store_true')
    arg_parser.add_argument('--stable-releases-limit', type=int, default='3')
    arg_parser.add_argument('--lts-releases-limit', type=int, default='2')
    arg_parser.add_argument('--nav-limit', type=int, default='0')
    arg_parser.add_argument('--version-prefix', type=str, default='')
    arg_parser.add_argument('--is-stable-release', action='store_true')
    arg_parser.add_argument('--skip-multi-page', action='store_true')
    arg_parser.add_argument('--skip-single-page', action='store_true')
    arg_parser.add_argument('--skip-amp', action='store_true')
    arg_parser.add_argument('--skip-pdf', action='store_true')
    arg_parser.add_argument('--skip-website', action='store_true')
    arg_parser.add_argument('--skip-blog', action='store_true')
    arg_parser.add_argument('--skip-git-log', action='store_true')
    arg_parser.add_argument('--test-only', action='store_true')
    arg_parser.add_argument('--minify', action='store_true')
    arg_parser.add_argument('--htmlproofer', action='store_true')
    arg_parser.add_argument('--no-docs-macros', action='store_true')
    arg_parser.add_argument('--save-raw-single-page', type=str)
    arg_parser.add_argument('--livereload', type=int, default='0')
    arg_parser.add_argument('--verbose', action='store_true')
    args = arg_parser.parse_args()
    logging.basicConfig(level=logging.DEBUG if args.verbose else logging.
        INFO, stream=sys.stderr)
    logging.getLogger('MARKDOWN').setLevel(logging.INFO)
    args.docs_output_dir = os.path.join(os.path.abspath(args.output_dir),
        'docs')
    args.blog_output_dir = os.path.join(os.path.abspath(args.output_dir),
        'blog')
    from github import choose_latest_releases, get_events
    args.stable_releases = choose_latest_releases(args
        ) if args.enable_stable_releases else []
    args.rev = subprocess.check_output('git rev-parse HEAD', shell=True
        ).decode('utf-8').strip()
    args.rev_short = subprocess.check_output('git rev-parse --short HEAD',
        shell=True).decode('utf-8').strip()
    args.rev_url = (
        f'https://github.com/ClickHouse/ClickHouse/commit/{args.rev}')
    args.events = get_events(args)
    if args.test_only:
        args.skip_multi_page = True
        args.skip_blog = True
        args.skip_website = True
        args.skip_pdf = True
        args.skip_amp = True
    if args.skip_git_log or args.skip_amp:
        mdx_clickhouse.PatchedMacrosPlugin.skip_git_log = True
    from build import build
    build(args)
    if args.livereload:
        new_args = [arg for arg in sys.argv if not arg.startswith(
            '--livereload')]
        new_args = sys.executable + ' ' + ' '.join(new_args)
        server = livereload.Server()
        server.watch(args.docs_dir + '**/*', livereload.shell(new_args, cwd
            ='tools', shell=True))
        server.watch(args.website_dir + '**/*', livereload.shell(new_args,
            cwd='tools', shell=True))
        server.serve(root=args.output_dir, host='0.0.0.0', port=args.livereload
            )
        sys.exit(0)

#!/usr/bin/env python3

import argparse
import datetime
import logging
import os
import shutil
import subprocess
import sys
import time

import jinja2
import livereload
import markdown.util

import nav  # monkey patches mkdocs

from mkdocs import config
from mkdocs import exceptions
import mkdocs.commands.build

import amp
import blog
import mdx_clickhouse
import redirects
import single_page
import test
import util
import website


class ClickHouseMarkdown(markdown.extensions.Extension):
    class ClickHousePreprocessor(markdown.util.Processor):
        def run(self, lines):
            for line in lines:
                if '<!--hide-->' not in line:
                    yield line

    def extendMarkdown(self, md):
        md.preprocessors.register(self.ClickHousePreprocessor(), 'clickhouse_preprocessor', 31)


markdown.extensions.ClickHouseMarkdown = ClickHouseMarkdown


def build_for_lang(lang, args):
    logging.info(f'Building {lang} docs')
    os.environ['SINGLE_PAGE'] = '0'

    config_path = os.path.join(args.docs_dir, f'toc_{lang}.yml')
    if args.is_stable_release and not os.path.exists(config_path):
        logging.warning(f'Skipping {lang} docs, because {config} does not exist')
        return

    try:
        theme_cfg = {
            'name': None,
            'custom_dir': os.path.join(os.path.dirname(__file__), '..', args.theme_dir),
            'language': lang,
            'direction': 'rtl' if lang == 'fa' else 'ltr',
            'static_templates': ['404.html'],
            'extra': {
                'now': int(time.mktime(datetime.datetime.now().timetuple()))  # TODO better way to avoid caching
            }
        }

        # the following list of languages is sorted according to
        # https://en.wikipedia.org/wiki/List_of_languages_by_total_number_of_speakers
        languages = {
            'en': 'English',
            'zh': '中文',
            'es': 'Español',
            'fr': 'Français',
            'ru': 'Русский',
            'ja': '日本語',
            'tr': 'Türkçe',
            'fa': 'فارسی'
        }

        site_names = {
            'en': 'ClickHouse %s Documentation',
            'zh': 'ClickHouse文档 %s',
            'es': 'Documentación de ClickHouse %s',
            'fr': 'Documentation ClickHouse %s',
            'ru': 'Документация ClickHouse %s',
            'ja': 'ClickHouseドキュメント %s',
            'tr': 'ClickHouse Belgeleri %s',
            'fa': 'مستندات %sClickHouse'
        }

        assert len(site_names) == len(languages)

        if args.version_prefix:
            site_dir = os.path.join(args.docs_output_dir, args.version_prefix, lang)
        else:
            site_dir = os.path.join(args.docs_output_dir, lang)

        plugins = ['macros']
        if args.htmlproofer:
            plugins.append('htmlproofer')

        website_url = 'https://clickhouse.tech'
        site_name = site_names.get(lang, site_names['en']) % args.version_prefix
        site_name = site_name.replace('  ', ' ')
        raw_config = dict(
            site_name=site_name,
            site_url=f'{website_url}/docs/{lang}/',
            docs_dir=os.path.join(args.docs_dir, lang),
            site_dir=site_dir,
            strict=not args.version_prefix,
            theme=theme_cfg,
            copyright='©2016–2020 Yandex LLC',
            use_directory_urls=True,
            repo_name='ClickHouse/ClickHouse',
            repo_url='https://github.com/ClickHouse/ClickHouse/',
            edit_uri=f'edit/master/docs/{lang}',
            markdown_extensions=mdx_clickhouse.MARKDOWN_EXTENSIONS,
            plugins=plugins,
            extra=dict(
                now=datetime.datetime.now().isoformat(),
                stable_releases=args.stable_releases,
                version_prefix=args.version_prefix,
                single_page=False,
                rev=args.rev,
                rev_short=args.rev_short,
                rev_url=args.rev_url,
                website_url=website_url,
                events=args.events,
                languages=languages,
                includes_dir=os.path.join(os.path.dirname(__file__), '..', '_includes'),
                is_amp=False,
                is_blog=False
            )
        )

        if os.path.exists(config_path):
            raw_config['config_file'] = config_path
        else:
            raw_config['nav'] = nav.build_docs_nav(lang, args)

        cfg = config.load_config(**raw_config)

        if not args.skip_multi_page:
            try:
                mkdocs.commands.build.build(cfg)
            except jinja2.exceptions.TemplateError:
                if not args.version_prefix:
                    raise
                mdx_clickhouse.PatchedMacrosPlugin.disabled = True
                mkdocs.commands.build.build(cfg)

        if not (args.skip_amp or args.version_prefix):
            amp.build_amp(lang, args, cfg)

        if not args.skip_single_page:
            single_page.build_single_page_version(lang, args, raw_config.get('nav'), cfg)

        mdx_clickhouse.PatchedMacrosPlugin.disabled = False

        logging.info(f'Finished building {lang} docs')

    except exceptions.ConfigurationError as e:
        raise SystemExit('\n' + str(e))


def build_docs(args):
    tasks = []
    for lang in args.lang.split(','):
        if lang:
            tasks.append((lang, args,))
    util.run_function_in_parallel(build_for_lang, tasks, threads=False)
    if not args.version_prefix:
        redirects.build_docs_redirects(args)


def build(args):
    if os.path.exists(args.output_dir):
        shutil.rmtree(args.output_dir)

    if not args.skip_website:
        website.build_website(args)

    test.test_templates(args.website_dir)

    build_docs(args)

    from github import build_releases
    build_releases(args, build_docs)

    if not args.skip_blog:
        blog.build_blog(args)

    if not args.skip_website:
        website.process_benchmark_results(args)
        website.minify_website(args)
        redirects.build_static_redirects(args)


if __name__ == '__main__':
    os.chdir(os.path.join(os.path.dirname(__file__), '..'))
    website_dir = os.path.join('..', 'website')
    arg_parser = argparse.ArgumentParser()
    arg_parser.add_argument('--lang', default='en,es,fr,ru,zh,ja,tr,fa')
    arg_parser.add_argument('--blog-lang', default='en,ru')
    arg_parser.add_argument('--docs-dir', default='.')
    arg_parser.add_argument('--theme-dir', default=website_dir)
    arg_parser.add_argument('--website-dir', default=website_dir)
    arg_parser.add_argument('--blog-dir', default=os.path.join(website_dir, 'blog'))
    arg_parser.add_argument('--output-dir', default='build')
    arg_parser.add_argument('--enable-stable-releases', action='store_true')
    arg_parser.add_argument('--stable-releases-limit', type=int, default='3')
    arg_parser.add_argument('--lts-releases-limit', type=int, default='2')
    arg_parser.add_argument('--nav-limit', type=int, default='0')
    arg_parser.add_argument('--version-prefix', type=str, default='')
    arg_parser.add_argument('--is-stable-release', action='store_true')
    arg_parser.add_argument('--skip-multi-page', action='store_true')
    arg_parser.add_argument('--skip-single-page', action='store_true')
    arg_parser.add_argument('--skip-amp', action='store_true')
    arg_parser.add_argument('--skip-pdf', action='store_true')
    arg_parser.add_argument('--skip-website', action='store_true')
    arg_parser.add_argument('--skip-blog', action='store_true')
    arg_parser.add_argument('--skip-git-log', action='store_true')
    arg_parser.add_argument('--test-only', action='store_true')
    arg_parser.add_argument('--minify', action='store_true')
    arg_parser.add_argument('--htmlproofer', action='store_true')
    arg_parser.add_argument('--no-docs-macros', action='store_true')
    arg_parser.add_argument('--save-raw-single-page', type=str)
    arg_parser.add_argument('--livereload', type=int, default='0')
    arg_parser.add_argument('--verbose', action='store_true')

    args = arg_parser.parse_args()

    logging.basicConfig(
        level=logging.DEBUG if args.verbose else logging.INFO,
        stream=sys.stderr
    )

    logging.getLogger('MARKDOWN').setLevel(logging.INFO)

    args.docs_output_dir = os.path.join(os.path.abspath(args.output_dir), 'docs')
    args.blog_output_dir = os.path.join(os.path.abspath(args.output_dir), 'blog')

    from github import choose_latest_releases, get_events
    args.stable_releases = choose_latest_releases(args) if args.enable_stable_releases else []
    args.rev = subprocess.check_output('git rev-parse HEAD', shell=True).decode('utf-8').strip()
    args.rev_short = subprocess.check_output('git rev-parse --short HEAD', shell=True).decode('utf-8').strip()
    args.rev_url = f'https://github.com/ClickHouse/ClickHouse/commit/{args.rev}'
    args.events = get_events(args)

    if args.test_only:
        args.skip_multi_page = True
        args.skip_blog = True
        args.skip_website = True
        args.skip_pdf = True
        args.skip_amp = True

    if args.skip_git_log or args.skip_amp:
        mdx_clickhouse.PatchedMacrosPlugin.skip_git_log = True

    from build import build
    build(args)

    if args.livereload:
        new_args = [arg for arg in sys.argv if not arg.startswith('--livereload')]
        new_args = sys.executable + ' ' + ' '.join(new_args)

        server = livereload.Server()
        server.watch(args.docs_dir + '**/*', livereload.shell(new_args, cwd='tools', shell=True))
        server.watch(args.website_dir + '**/*', livereload.shell(new_args, cwd='tools', shell=True))
        server.serve(
            root=args.output_dir,
            host='0.0.0.0',
            port=args.livereload
        )
        sys.exit(0)
