2020-10-02 16:54:07 +00:00
|
|
|
#!/usr/bin/env python3
|
2018-10-16 10:47:17 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
2020-10-02 16:54:07 +00:00
|
|
|
|
2018-10-16 10:47:17 +00:00
|
|
|
|
2020-05-08 08:04:09 +00:00
|
|
|
import datetime
|
2018-12-12 17:28:00 +00:00
|
|
|
import os
|
2020-05-08 08:04:09 +00:00
|
|
|
import subprocess
|
2018-12-12 17:28:00 +00:00
|
|
|
|
2020-04-24 09:50:22 +00:00
|
|
|
import jinja2
|
2018-12-07 16:24:54 +00:00
|
|
|
import markdown.inlinepatterns
|
2018-10-16 10:47:17 +00:00
|
|
|
import markdown.extensions
|
|
|
|
import markdown.util
|
2020-03-18 13:02:32 +00:00
|
|
|
import macros.plugin
|
2018-10-16 10:47:17 +00:00
|
|
|
|
2018-12-12 17:28:00 +00:00
|
|
|
import slugify as slugify_impl
|
|
|
|
|
2020-03-31 11:22:56 +00:00
|
|
|
|
2020-06-16 06:31:00 +00:00
|
|
|
def slugify(value, separator):
|
|
|
|
return slugify_impl.slugify(value, separator=separator, word_boundary=True, save_order=True)
|
|
|
|
|
|
|
|
|
|
|
|
MARKDOWN_EXTENSIONS = [
|
|
|
|
'mdx_clickhouse',
|
|
|
|
'admonition',
|
|
|
|
'attr_list',
|
2020-06-24 12:59:19 +00:00
|
|
|
'def_list',
|
2020-06-16 06:31:00 +00:00
|
|
|
'codehilite',
|
|
|
|
'nl2br',
|
|
|
|
'sane_lists',
|
|
|
|
'pymdownx.details',
|
|
|
|
'pymdownx.magiclink',
|
|
|
|
'pymdownx.superfences',
|
|
|
|
'extra',
|
|
|
|
{
|
|
|
|
'toc': {
|
|
|
|
'permalink': True,
|
|
|
|
'slugify': slugify
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
|
|
|
|
|
|
|
|
2018-12-12 17:28:00 +00:00
|
|
|
class ClickHouseLinkMixin(object):
|
2018-10-16 10:47:17 +00:00
|
|
|
|
2020-03-18 13:02:32 +00:00
|
|
|
def handleMatch(self, m, data):
|
2018-12-12 17:28:00 +00:00
|
|
|
single_page = (os.environ.get('SINGLE_PAGE') == '1')
|
2018-12-07 16:24:54 +00:00
|
|
|
try:
|
2020-03-18 13:02:32 +00:00
|
|
|
el, start, end = super(ClickHouseLinkMixin, self).handleMatch(m, data)
|
2018-12-07 16:24:54 +00:00
|
|
|
except IndexError:
|
|
|
|
return
|
|
|
|
|
|
|
|
if el is not None:
|
|
|
|
href = el.get('href') or ''
|
2018-12-12 17:28:00 +00:00
|
|
|
is_external = href.startswith('http:') or href.startswith('https:')
|
2018-12-18 11:32:08 +00:00
|
|
|
if is_external:
|
2020-03-18 13:02:32 +00:00
|
|
|
if not href.startswith('https://clickhouse.tech'):
|
2020-03-30 08:25:29 +00:00
|
|
|
el.set('rel', 'external nofollow noreferrer')
|
2018-12-12 17:28:00 +00:00
|
|
|
elif single_page:
|
|
|
|
if '#' in href:
|
|
|
|
el.set('href', '#' + href.split('#', 1)[1])
|
|
|
|
else:
|
2018-12-18 11:32:08 +00:00
|
|
|
el.set('href', '#' + href.replace('/index.md', '/').replace('.md', '/'))
|
2020-03-18 13:02:32 +00:00
|
|
|
return el, start, end
|
2018-12-07 16:24:54 +00:00
|
|
|
|
|
|
|
|
2020-03-18 13:02:32 +00:00
|
|
|
class ClickHouseAutolinkPattern(ClickHouseLinkMixin, markdown.inlinepatterns.AutolinkInlineProcessor):
|
2018-12-07 16:24:54 +00:00
|
|
|
pass
|
|
|
|
|
|
|
|
|
2020-03-18 13:02:32 +00:00
|
|
|
class ClickHouseLinkPattern(ClickHouseLinkMixin, markdown.inlinepatterns.LinkInlineProcessor):
|
2018-12-07 16:24:54 +00:00
|
|
|
pass
|
|
|
|
|
|
|
|
|
2018-10-16 10:47:17 +00:00
|
|
|
class ClickHousePreprocessor(markdown.util.Processor):
|
|
|
|
def run(self, lines):
|
2018-12-21 19:40:49 +00:00
|
|
|
if os.getenv('QLOUD_TOKEN'):
|
|
|
|
for line in lines:
|
|
|
|
if '<!--hide-->' not in line:
|
|
|
|
yield line
|
2018-12-25 08:43:07 +00:00
|
|
|
else:
|
|
|
|
for line in lines:
|
|
|
|
yield line
|
2018-10-16 10:47:17 +00:00
|
|
|
|
2018-12-07 16:24:54 +00:00
|
|
|
|
2018-10-16 10:47:17 +00:00
|
|
|
class ClickHouseMarkdown(markdown.extensions.Extension):
|
|
|
|
|
|
|
|
def extendMarkdown(self, md, md_globals):
|
|
|
|
md.preprocessors['clickhouse'] = ClickHousePreprocessor()
|
2018-12-12 17:28:00 +00:00
|
|
|
md.inlinePatterns['link'] = ClickHouseLinkPattern(markdown.inlinepatterns.LINK_RE, md)
|
|
|
|
md.inlinePatterns['autolink'] = ClickHouseAutolinkPattern(markdown.inlinepatterns.AUTOLINK_RE, md)
|
2018-10-16 10:47:17 +00:00
|
|
|
|
2020-03-18 13:02:32 +00:00
|
|
|
|
2018-10-16 10:47:17 +00:00
|
|
|
def makeExtension(**kwargs):
|
|
|
|
return ClickHouseMarkdown(**kwargs)
|
2018-12-12 17:28:00 +00:00
|
|
|
|
2020-03-18 13:02:32 +00:00
|
|
|
|
2020-03-30 08:25:29 +00:00
|
|
|
def get_translations(dirname, lang):
|
|
|
|
import babel.support
|
|
|
|
return babel.support.Translations.load(
|
|
|
|
dirname=dirname,
|
|
|
|
locales=[lang, 'en']
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2020-03-18 13:02:32 +00:00
|
|
|
class PatchedMacrosPlugin(macros.plugin.MacrosPlugin):
|
2020-03-30 08:25:29 +00:00
|
|
|
disabled = False
|
2020-05-12 14:09:36 +00:00
|
|
|
skip_git_log = False
|
2020-03-30 08:25:29 +00:00
|
|
|
|
2020-03-18 13:02:32 +00:00
|
|
|
def on_config(self, config):
|
|
|
|
super(PatchedMacrosPlugin, self).on_config(config)
|
|
|
|
self.env.comment_start_string = '{##'
|
|
|
|
self.env.comment_end_string = '##}'
|
2020-04-24 09:50:22 +00:00
|
|
|
self.env.loader = jinja2.FileSystemLoader([
|
|
|
|
os.path.join(config.data['site_dir']),
|
|
|
|
os.path.join(config.data['extra']['includes_dir'])
|
|
|
|
])
|
2020-03-18 13:02:32 +00:00
|
|
|
|
2020-03-30 08:25:29 +00:00
|
|
|
def on_env(self, env, config, files):
|
2020-06-30 18:22:07 +00:00
|
|
|
import util
|
2020-03-30 08:25:29 +00:00
|
|
|
env.add_extension('jinja2.ext.i18n')
|
|
|
|
dirname = os.path.join(config.data['theme'].dirs[0], 'locale')
|
|
|
|
lang = config.data['theme']['language']
|
|
|
|
env.install_gettext_translations(
|
|
|
|
get_translations(dirname, lang),
|
|
|
|
newstyle=True
|
|
|
|
)
|
2020-06-30 18:22:07 +00:00
|
|
|
util.init_jinja2_filters(env)
|
2020-03-30 08:25:29 +00:00
|
|
|
return env
|
|
|
|
|
|
|
|
def render(self, markdown):
|
|
|
|
if not self.disabled:
|
|
|
|
return self.render_impl(markdown)
|
|
|
|
else:
|
|
|
|
return markdown
|
|
|
|
|
2020-05-08 08:04:09 +00:00
|
|
|
def on_page_markdown(self, markdown, page, config, files):
|
|
|
|
markdown = super(PatchedMacrosPlugin, self).on_page_markdown(markdown, page, config, files)
|
2020-05-18 14:43:38 +00:00
|
|
|
|
|
|
|
if os.path.islink(page.file.abs_src_path):
|
|
|
|
lang = config.data['theme']['language']
|
|
|
|
page.canonical_url = page.canonical_url.replace(f'/{lang}/', '/en/', 1)
|
|
|
|
|
2020-05-08 08:04:09 +00:00
|
|
|
if config.data['extra'].get('version_prefix') or config.data['extra'].get('single_page'):
|
|
|
|
return markdown
|
2020-05-12 14:09:36 +00:00
|
|
|
if self.skip_git_log:
|
|
|
|
return markdown
|
2020-05-08 08:04:09 +00:00
|
|
|
src_path = page.file.abs_src_path
|
|
|
|
try:
|
|
|
|
git_log = subprocess.check_output(f'git log --follow --date=iso8601 "{src_path}"', shell=True)
|
|
|
|
except subprocess.CalledProcessError:
|
|
|
|
return markdown
|
|
|
|
max_date = None
|
|
|
|
min_date = None
|
|
|
|
for line in git_log.decode('utf-8').split('\n'):
|
|
|
|
if line.startswith('Date:'):
|
|
|
|
line = line.replace('Date:', '').strip().replace(' ', 'T', 1).replace(' ', '')
|
|
|
|
current_date = datetime.datetime.fromisoformat(line[:-2] + ':' + line[-2:])
|
|
|
|
if (not max_date) or current_date > max_date:
|
|
|
|
max_date = current_date
|
|
|
|
if (not min_date) or current_date < min_date:
|
|
|
|
min_date = current_date
|
|
|
|
if min_date:
|
|
|
|
page.meta['published_date'] = min_date
|
|
|
|
if max_date:
|
|
|
|
page.meta['modified_date'] = max_date
|
|
|
|
return markdown
|
|
|
|
|
2020-03-30 08:25:29 +00:00
|
|
|
def render_impl(self, markdown):
|
|
|
|
md_template = self.env.from_string(markdown)
|
|
|
|
return md_template.render(**self.variables)
|
|
|
|
|
2020-03-18 13:02:32 +00:00
|
|
|
|
|
|
|
macros.plugin.MacrosPlugin = PatchedMacrosPlugin
|