未验证 提交 06f8f5de 编写于 作者: A alexey-milovidov 提交者: GitHub

Merge pull request #3369 from blinkov/master

Improvements around docs infrastructure
......@@ -36,3 +36,12 @@ The following features are planned for development:
- Cluster management.
- Monitoring replicated and Kafka tables.
## DBeaver
[DBeaver](https://dbeaver.io/) - universal desktop database client with ClickHouse support.
Key features:
- Query development with syntax highlight.
- Table preview.
- Autocompletion.
......@@ -42,5 +42,7 @@
- [clickhouse_ecto](https://github.com/appodeal/clickhouse_ecto)
- Java
- [clickhouse-client-java](https://github.com/VirtusAI/clickhouse-client-java)
- Kotlin
- [AORM](https://github.com/TanVD/AORM)
- Nim
- [nim-clickhouse](https://github.com/leonardoce/nim-clickhouse)
......@@ -6,10 +6,10 @@
Основные возможности:
- Работает с ClickHouse напрямую из браузера, без необходимости установки дополнительного ПО.
- Редактор запросов с подсветкой синтаксиса.
- Автодополнение команд.
- Инструменты графического анализа выполнения запросов.
- Работает с ClickHouse напрямую из браузера, без необходимости установки дополнительного ПО;
- Редактор запросов с подсветкой синтаксиса;
- Автодополнение команд;
- Инструменты графического анализа выполнения запросов;
- Цветовые схемы на выбор.
[Документация Tabix](https://tabix.io/doc/).
......@@ -20,28 +20,31 @@
Основные возможности:
- Построение запросов с подсветкой синтаксиса. Просмотр ответа в табличном или JSON представлении.
- Экспортирование результатов запроса в формате CSV или JSON.
- Список процессов с описанием. Режим записи. Возможность остановки (`KILL`) процесса.
- Граф базы данных. Показывает все таблицы и их столбцы с дополнительной информацией.
- Быстрый просмотр размера столбца.
- Построение запросов с подсветкой синтаксиса;
- Просмотр ответа в табличном или JSON представлении;
- Экспортирование результатов запроса в формате CSV или JSON;
- Список процессов с описанием;
- Режим записи;
- Возможность остановки (`KILL`) запроса;
- Граф базы данных. Показывает все таблицы и их столбцы с дополнительной информацией;
- Быстрый просмотр размера столбца;
- Конфигурирование сервера.
Планируется разработка следующих возможностей:
- Управление базами.
- Управление пользователями.
- Анализ данных в режиме реального времени.
- Мониторинг кластера.
- Управление кластером.
- Управление базами;
- Управление пользователями;
- Анализ данных в режиме реального времени;
- Мониторинг кластера;
- Управление кластером;
- Мониторинг реплицированных и Kafka таблиц.
## DBeaver
[DBeaver](https://dbeaver.io/) - Универсальный клиент баз данных
[DBeaver](https://dbeaver.io/) - универсальный desktop клиент баз данных с поддержкой ClickHouse.
Основные возможности:
- Построение запросов с подсветкой синтаксиса
- Просмотр таблиц
- Автодополнение команд
- Построение запросов с подсветкой синтаксиса;
- Просмотр таблиц;
- Автодополнение команд.
......@@ -16,7 +16,7 @@ Usually those have some way to preview how Markdown will look like, which allows
It'll take some effort to go through, but the result will be very close to production documentation.
For the first time you'll need to set up virtualenv:
For the first time you'll need to install [wkhtmltopdf](https://wkhtmltopdf.org/) and set up virtualenv:
``` bash
$ cd ClickHouse/docs/tools
......
......@@ -8,6 +8,7 @@ import datetime
import logging
import os
import shutil
import subprocess
import sys
import tempfile
......@@ -61,10 +62,8 @@ def build_for_lang(lang, args):
'static_templates': ['404.html'],
'extra': {
'single_page': False,
'opposite_lang': 'ru' if lang == 'en' else 'en',
'now': datetime.datetime.now() # TODO better way to avoid caching
}
}
site_names = {
......@@ -134,8 +133,7 @@ def build_single_page_version(lang, args, cfg):
'docs_dir': docs_temp_lang,
'site_dir': site_temp,
'extra': {
'single_page': True,
'opposite_lang': 'en' if lang == 'ru' else 'ru'
'single_page': True
},
'nav': [
{cfg.data.get('site_name'): 'single.md'}
......@@ -154,6 +152,12 @@ def build_single_page_version(lang, args, cfg):
single_page_output_path
)
single_page_index_html = os.path.abspath(os.path.join(single_page_output_path, 'index.html'))
single_page_pdf = single_page_index_html.replace('index.html', 'clickhouse_%s.pdf' % lang)
create_pdf_command = ['wkhtmltopdf', '--print-media-type', single_page_index_html, single_page_pdf]
logging.debug(' '.join(create_pdf_command))
subprocess.check_call(' '.join(create_pdf_command), shell=True)
def build_redirects(args):
lang_re_fragment = args.lang.replace(',', '|')
......
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 30" preserveAspectRatio="none">
<clipPath id="t">
<path d="M30,15 h30 v15 z v15 h-30 z h-30 v-15 z v-15 h30 z"/>
</clipPath>
<path d="M0,0 v30 h60 v-30 z" fill="#00247d"/>
<path d="M0,0 L60,30 M60,0 L0,30" stroke="#fff" stroke-width="6"/>
<path d="M0,0 L60,30 M60,0 L0,30" clip-path="url(#t)" stroke="#cf142b" stroke-width="4"/>
<path d="M30,0 v30 M0,15 h60" stroke="#fff" stroke-width="10"/>
<path d="M30,0 v30 M0,15 h60" stroke="#cf142b" stroke-width="6"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 630 360" preserveAspectRatio="none">
<rect width="630" height="360" fill="#da0000"/>
<rect width="630" height="240" fill="#fff"/>
<rect width="630" height="120" fill="#239f40"/>
<g transform="translate(8.4,100.4)">
<g id="tb4">
<g id="tb1" fill="none" stroke="#fff" stroke-width="2">
<path id="tbp1" d="M0,1H26M1,10V5H9V9H17V5H12M4,9H6M26,9H21V5H29M29,0V9H37V0M33,0V9" transform="scale(1.4)"/>
<path id="tbp2" d="M0,7H9M10,7H19" transform="scale(2.8)"/>
<use xlink:href="#tbp2" y="120"/>
<use xlink:href="#tbp1" y="145.2"/>
</g>
<g id="tb3">
<use xlink:href="#tb1" x="56"/>
<use xlink:href="#tb1" x="112"/>
<use xlink:href="#tb1" x="168"/>
</g>
</g>
<use xlink:href="#tb3" x="168"/>
<use xlink:href="#tb4" x="392"/>
</g>
<g fill="#da0000" transform="matrix(45,0,0,45,315,180)">
<g id="emblem_half">
<path d="M-0.54815,0.83638A0.912046,0.912046 0 0,0 0.328544,-0.722384A1,1 0 0,1 -0.54815,0.83638"/>
<path d="M0.618339,0.661409A0.763932,0.763932 0 0,0 0.421644,-0.741049A1,1 0 0,1 0.618339,0.661409"/>
<path d="M0,1 -0.05,0 0,-0.787278A0.309995,0.309995 0 0,0 0.118034,-0.688191V-0.100406L0.077809,0.892905z"/>
<path d="M-0.02,-0.85 0,-0.831217A0.14431,0.14431 0 0,0 0.252075,-0.967708A0.136408,0.136408 0 0,1 0,-0.924634"/>
</g>
<use xlink:href="#emblem_half" transform="scale(-1,1)"/>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 9 6" preserveAspectRatio="none">
<rect fill="#fff" width="9" height="3"/>
<rect fill="#d52b1e" y="3" width="9" height="3"/>
<rect fill="#0039a6" y="2" width="9" height="2"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 30 20" preserveAspectRatio="none">
<defs>
<path id="s" d="M0,-1 0.587785,0.809017 -0.951057,-0.309017H0.951057L-0.587785,0.809017z" fill="#ffde00"/>
</defs>
<rect width="30" height="20" fill="#de2910"/>
<use xlink:href="#s" transform="translate(5,5) scale(3)"/>
<use xlink:href="#s" transform="translate(10,2) rotate(23.036243)"/>
<use xlink:href="#s" transform="translate(12,4) rotate(45.869898)"/>
<use xlink:href="#s" transform="translate(12,7) rotate(69.945396)"/>
<use xlink:href="#s" transform="translate(10,9) rotate(20.659808)"/>
</svg>
i/**
* lunr对中文分词的支持
*/
;
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function() {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
/*
Thai tokenization is the same to Japanense, which does not take into account spaces.
So, it uses the same logic to assign tokenization function due to different Lunr versions.
*/
var isLunr2 = lunr.version[0] == "2";
/* register specific locale function */
lunr.zhcn = function() {
this.pipeline.reset();
this.pipeline.add(
lunr.zhcn.trimmer,
lunr.zhcn.stopWordFilter,
lunr.zhcn.stemmer
);
if (isLunr2) { // for lunr version 2.0.0
this.tokenizer = lunr.zhcn.tokenizer;
} else {
if (lunr.tokenizer) { // for lunr version 0.6.0
lunr.tokenizer = lunr.zhcn.tokenizer;
}
if (this.tokenizerFn) { // for lunr version 0.7.0 -> 1.0.0
this.tokenizerFn = lunr.zhcn.tokenizer;
}
}
};
var segmenter = new lunr.TinySegmenter();
lunr.zhcn.tokenizer = function(obj) {
var i;
var str;
var len;
var segs;
var tokens;
var char;
var sliceLength;
var sliceStart;
var sliceEnd;
var segStart;
if (!arguments.length || obj == null || obj == undefined)
return [];
if (Array.isArray(obj)) {
return obj.map(
function(t) {
return isLunr2 ? new lunr.Token(t.toLowerCase()) : t.toLowerCase();
}
);
}
str = obj.toString().toLowerCase().replace(/^\s+/, '');
for (i = str.length - 1; i >= 0; i--) {
if (/\S/.test(str.charAt(i))) {
str = str.substring(0, i + 1);
break;
}
}
tokens = [];
len = str.length;
for (sliceEnd = 0, sliceStart = 0; sliceEnd <= len; sliceEnd++) {
char = str.charAt(sliceEnd);
sliceLength = sliceEnd - sliceStart;
if ((char.match(/\s/) || sliceEnd == len)) {
if (sliceLength > 0) {
segs = segmenter.segment(str.slice(sliceStart, sliceEnd)).filter(
function(token) {
return !!token;
}
);
segStart = sliceStart;
for (i = 0; i < segs.length; i++) {
if (isLunr2) {
tokens.push(
new lunr.Token(
segs[i], {
position: [segStart, segs[i].length],
index: tokens.length
}
)
);
} else {
tokens.push(segs[i]);
}
segStart += segs[i].length;
}
}
sliceStart = sliceEnd + 1;
}
}
return tokens;
}
lunr.zhcn.stemmer = (function(){
return function(word) {
return word;
}
})();
lunr.Pipeline.registerFunction(lunr.zhcn.stemmer, 'stemmer-zhcn');
/* lunr trimmer function */
lunr.zhcn.wordCharacters = "一二三四五六七八九十百千万億兆一-龠々〆ヵヶぁ-んァ-ヴーア-ン゙a-zA-Za-zA-Z0-90-9";
lunr.zhcn.trimmer = lunr.trimmerSupport.generateTrimmer(lunr.zhcn.wordCharacters);
lunr.Pipeline.registerFunction(lunr.zhcn.trimmer, 'trimmer-zhcn');
/* lunr stop word filter. see https://www.ranks.nl/stopwords/chinese-stopwords */
lunr.zhcn.stopWordFilter = lunr.generateStopWordFilter('的 一 不 在 人 有 是 为 以 于 上 他 而 后 之 来 及 了 因 下 可 到 由 这 与 也 此 但 并 个 其 已 无 小 我 们 起 最 再 今 去 好 只 又 或 很 亦 某 把 那 你 乃 它 吧 被 比 别 趁 当 从 到 得 打 凡 儿 尔 该 各 给 跟 和 何 还 即 几 既 看 据 距 靠 啦 了 另 么 每 们 嘛 拿 哪 那 您 凭 且 却 让 仍 啥 如 若 使 谁 虽 随 同 所 她 哇 嗡 往 哪 些 向 沿 哟 用 于 咱 则 怎 曾 至 致 着 诸 自'.split(' '));
lunr.Pipeline.registerFunction(lunr.zhcn.stopWordFilter, 'stopWordFilter-zhcn');
};
}))
......@@ -130,10 +130,34 @@ h1, h2, h3, .md-logo {
}
#md-extra-nav {
background: #efefef;
padding-top: 0.5rem;
background: #efefef;
padding: 0.5rem 0;
}
.grey {
color: #666;
color: #666;
}
.md-alt-lang:hover {
text-decoration: none;
}
.md-alt-lang>svg {
width: 36px;
height: 24px;
margin: 1.3rem 0;
filter: brightness(96%) grayscale(90%);
}
.md-alt-lang:hover>svg {
filter: brightness(96%) grayscale(5%);
}
.md-current-lang>svg {
filter: brightness(96%) grayscale(0%) !important;
}
@media only screen and (min-width: 60em) {
#md-sidebar-flags {
display: none;
}
}
{% set alt_langs = [['en', 'English'], ['ru', 'Russian'], ['zh', 'Chinese'], ['fa', 'Farsi']] %}
{% for alt_lang, alt_title in alt_langs %}
<a class="md-alt-lang{% if alt_lang == config.theme.language %} md-current-lang{% endif %}"
href="{{ base_url }}/../{{ alt_lang }}/{{ page.url or '' }}" class="md-flex__ellipsis md-header-nav__title"
title="{{ alt_title }}">
{% include "assets/flags/" + alt_lang + ".svg" %}
</a>
{% endfor %}
......@@ -43,24 +43,7 @@
{% if page %}
<div class="md-flex__cell md-flex__cell--shrink">
<div id="md-language-switch" class="md-header-nav__source">
{% if config.theme.extra.opposite_lang == 'en' %}
<a href="{{ base_url }}/../{{ config.theme.extra.opposite_lang }}/{{ page.url or '' }}" title="Switch to English" class="md-flex__ellipsis md-header-nav__title">
<svg xmlns="http://www.w3.org/2000/svg" width="50" height="30" viewBox="0,0 25,15" style="border:1px solid #eee;margin: .8rem 0 0 -1.25rem;">
<rect width="25" height="15" fill="#00247d"></rect>
<path d="M 0,0 L 25,15 M 25,0 L 0,15" stroke="#fff" stroke-width="3"></path>
<path d="M 12.5,0 V 15 M 0,7.5 H 25" stroke="#fff" stroke-width="5"></path>
<path d="M 12.5,0 V 15 M 0,7.5 H 25" stroke="#cf142b" stroke-width="3"></path>
</svg>
</a>
{% else %}
<a href="{{ base_url }}/../{{ config.theme.extra.opposite_lang }}/{{ page.url or '' }}" title="Переключить на русский язык" class="md-flex__ellipsis md-header-nav__title">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 6" width="50" height="30" style="border: 1px solid #eee;margin: .8rem 0 0 -1.25rem">
<rect fill="#fff" width="10" height="3"></rect>
<rect fill="#d52b1e" y="3" width="10" height="3"></rect>
<rect fill="#0039a6" y="2" width="10" height="2"></rect>
</svg>
</a>
{% endif %}
{% include "partials/flags.html" %}
</div>
</div>
{% endif %}
......
......@@ -29,6 +29,13 @@
{% endif %}
{% endif %}
</li>
<li class="md-nav__item md-nav__item--active">
{% if config.theme.language == 'ru' %}
<a href="{{ base_url }}/single/clickhouse_{{ config.theme.language }}.pdf" class="md-nav__link md-nav__link--active">PDF версия</a>
{% else %}
<a href="{{ base_url }}/single/clickhouse_{{ config.theme.language }}.pdf" class="md-nav__link md-nav__link--active">PDF version</a>
{% endif %}
</li>
{% if config.repo_url %}
<li class="md-nav__item md-nav__item--active">
<a href="{{ config.repo_url }}" rel="external nofollow" target="_blank" class="md-nav__link">
......@@ -40,5 +47,10 @@
</a>
</li>
{% endif %}
<li class="md-nav__item md-nav__item--active">
<span id="md-sidebar-flags" class="md-nav__link">
{% include "partials/flags.html" %}
</span>
</li>
</ul>
</nav>
......@@ -26,6 +26,7 @@ var paths = {
docstxt: ['docs/**/*.txt', 'docs/redirects.conf'],
docsjson: ['docs/**/*.json'],
docsxml: ['docs/**/*.xml'],
docspdf: ['docs/**/*.pdf'],
docssitemap: ['sitemap.xml', 'sitemap_static.xml'],
scripts: [
'**/*.js',
......@@ -78,6 +79,11 @@ gulp.task('docsxml', ['docs'], function () {
.pipe(gulp.dest(outputDir + '/docs'))
});
gulp.task('docspdf', ['docs'], function () {
return gulp.src(paths.docspdf)
.pipe(gulp.dest(outputDir + '/docs'))
});
gulp.task('docssitemap', [], function () {
return gulp.src(paths.docssitemap)
.pipe(gulp.dest(outputDir + '/docs'))
......@@ -93,7 +99,7 @@ gulp.task('robotstxt', [], function () {
.pipe(gulp.dest(outputDir))
});
gulp.task('htmls', ['docs', 'docstxt', 'docsjson', 'docsxml', 'docssitemap'], function () {
gulp.task('htmls', ['docs', 'docstxt', 'docsjson', 'docsxml', 'docspdf', 'docssitemap'], function () {
return gulp.src(paths.htmls)
.pipe(htmlmin({collapseWhitespace: true}))
.pipe(minifyInline())
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册