feat: codefever-community documentation system

This commit is contained in:
pololi
2022-01-14 15:35:36 +08:00
parent f5d6e3997c
commit cc89f394b2
10 changed files with 296 additions and 82 deletions

View File

@@ -20,8 +20,8 @@ class Doc extends Base
}
public function index ()
{
// doing nothing
{
// doing nothing
}
public function cn()
@@ -57,18 +57,35 @@ class Doc extends Base
$docDir = array_slice($segments, 2, -1);
}
$menuFile = $rootDir . ($docDir ? implode('/', $docDir) : '') . '/index.md';
$menuFile = $rootDir . 'index.md';
$menu = $this->_extractMenu($menuFile);
$menuOptions = $menu;
foreach ($menu as &$item) {
$menuFile = $rootDir . $item['path'] . '/index.md';
if (!file_exists($menuFile)) {
continue;
}
$submenu = $this->_extractMenu($menuFile);
foreach ($submenu as &$item2) {
$item2['path'] = $item['path'] . '/' . $item2['path'];
}
$item['submenu'] = $submenu;
}
if (!preg_match('/\.[a-z0-9]+/i', $docFile)) {
// docFile = /data/www/codefever-community/doc/zh-cn/installation
// menuFile = /data/www/codefever-community/doc/zh-cn/installation/index.md
$menuOptions = $this->_extractMenu($menuFile);
while ($menuOptions && count($menuOptions) > 0) {
$pathinfo = $_SERVER['PATH_INFO'];
while ($menu && count($menuOptions) > 0) {
if (strpos($menuOptions[0]['path'], '.') > 0) {
$docFile .= '/' . $menuOptions[0]['path'];
$pathinfo = rtrim($pathinfo, '/');
$pathinfo .= '/' . $menuOptions[0]['path'];
header("Location: $pathinfo");
break;
} else {
$pathinfo = rtrim($pathinfo, '/');
$pathinfo .= '/' . $menuOptions[0]['path'];
$docFile .= '/' . $menuOptions[0]['path'];
$menuOptions = $this->_extractMenu($docFile . '/index.md');
}
@@ -77,9 +94,8 @@ class Doc extends Base
$this->load->view('doc/detail', [
'segments' => $segments,
'menu' => str_replace('`', '\`', file_get_contents($menuFile)),
'menu' => $menu,
'doc' => str_replace('`', '\`', file_get_contents($docFile)),
'docName' => $this->_docName($rootDir),
]);
}
@@ -90,7 +106,7 @@ class Doc extends Base
$lines = explode("\n", $data);
foreach ($lines as $line) {
$matches = [];
if (preg_match('/\[(\S+)\]\((\S+)\)/', $line, $matches)) {
if (preg_match('/\[([^\]]+)\]\(([^\)]+)\)/', $line, $matches)) {
array_push($output, ['name' => $matches[1], 'path' => trim($matches[2])]);
}
}
@@ -98,33 +114,6 @@ class Doc extends Base
return $output;
}
private function _docName(string $rootDir)
{
return function (string $path) use ($rootDir) {
if (!$path) {
return FALSE;
}
$docDir = substr($path, 8);
$docDir = substr($docDir, 0, strrpos($docDir, '/'));
$indexFile = $rootDir . $docDir . '/index.md';
if (!file_exists($indexFile)) {
return FALSE;
}
$path = str_replace(["/", "."], ["\\/", "\\."], $path);
$data = file_get_contents($indexFile);
preg_match("/\[(.+)\]\({$path}\)/i", $data, $matches);
if (!$matches) {
return FALSE;
}
return $matches[1];
};
}
private function _assets($path)
{
if (!file_exists($path)) {

View File

@@ -7,3 +7,4 @@
$lang['base_go_home'] = 'Home';
$lang['base_go_prepage'] = 'Return to previous page';
$lang['base_confirm'] = 'Confirm';
$lang['base_directory'] = 'Directory';

View File

@@ -7,3 +7,4 @@ $lang['base_error_message_tips'] = '抱歉,请重新尝试访问网站,或
$lang['base_go_home'] = '返回主页';
$lang['base_go_prepage'] = '返回上一页';
$lang['base_confirm'] = '确定';
$lang['base_directory'] = '目录';

View File

@@ -6,59 +6,129 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Codefever community - Doc</title>
<link href="/static/vendor/bootstrap-4.4.1/css/bootstrap.min.css" rel="stylesheet" type="text/css"/>
<link href="/static/css/markdown.css" rel="stylesheet" type="text/css"/>
<?php include TPLPATH . 'newpage/header_include.php'; ?>
</head>
<body>
<div class="container-fluid markdown-body">
<div class="container-fluid">
<div class="row">
<div class="col-md-10">
<?php
$path = '/doc';
$length = count($segments);
for ($i = 1; $i < $length; $i++) {
$path .= '/' . $segments[$i];
$show = $docName($path);
$show = $show ? $show : $segments[$i];
<div class="col-md-2 bg-EFF3F8 color-2F354D doc-left">
<div><img class="doc-logo" src="/static/images/logo-community-doc.png" /></div>
<p class="weight-600"><?php echo lang('base_directory'); ?></p>
$show = $show == 'cn' ? lang('base_cn') : $show;
$show = $show == 'en' ? lang('base_en') : $show;
?>
<a href="<?php echo $path; ?>"><?php echo $show; ?></a>
<?php echo $i < $length - 1 ? '/' : ''; ?>
<?php foreach ($menu as $item) { ?>
<div class="menu opened">
<div class="menu-first flexRowRowCenter">
<span class="switch"></span>
<span class="ml-16"><?php echo $item['name']; ?></span>
</div>
<?php if ($item['submenu']) { ?>
<div class="menu-second">
<?php foreach ($item['submenu'] as $item2) { ?>
<div class="ml-50"><a class="normal-link" href="/doc/<?php echo $segments[1] . '/' . $item2['path']; ?>"><?php echo $item2['name']; ?></a></div>
<?php } ?>
</div>
<?php } ?>
</div>
<?php } ?>
</div>
<div class="col-md-2 text-right">
<?php if ($segments[1] == 'cn') { ?>
<a href="<?php echo str_replace('/doc/cn', '/doc/en', $path); ?>"><?php echo lang('base_en'); ?></a>
<?php } else { ?>
<a href="<?php echo str_replace('/doc/en', '/doc/cn', $path); ?>"><?php echo lang('base_cn'); ?></a>
<?php } ?>
</div>
</div>
<div class="row">
<div class="col-md-4">
<br>
<div class='menu'></div>
</div>
<div class="col-md-8">
<div class="doc"></div>
<div class="col-md-10 doc-right">
<div class="header flexRowCenter justifyContent">
<div class="title"><h1></h1></div>
<div>
<span class="lang mr-50">
<div class="flexRowCenter justifyContent">
<span><?php echo $segments[1] == 'cn' ? lang('base_cn') : lang('base_en'); ?></span>
<span class="switch"></span>
</div>
<div class="lang-menu">
<div><a class="normal-link <?php echo $segments[1] == 'cn' ? 'active' : ''; ?>" href="<?php echo '/doc/cn/' . implode('/', array_slice($segments, 2)); ?>"><?php echo lang('base_cn'); ?></a></div>
<div><a class="normal-link <?php echo $segments[1] == 'en' ? 'active' : ''; ?>" href="<?php echo '/doc/en/' . implode('/', array_slice($segments, 2)); ?>"><?php echo lang('base_en'); ?></a></div>
</div>
</span>
<a class="btn" href="/user/login"><?php echo lang('user_login_btn_login'); ?></a>
<a class="btn btn-self-primary" href="/user/register"><?php echo lang('user_form_register_page_title'); ?></a>
</div>
</div>
<div class="doc-content flexRowCenter justifyContent alignStart">
<div class="container doc markdown-body"></div>
<div class="doc-nav">
<div class="track"><div class="thumb"></div></div>
</div>
</div>
</div>
</div>
</div>
<script src="/static/vendor/jquery-3.5.0/jquery.min.js" type="text/javascript"></script>
<script src="/static/<?php echo RELEASENUMBER;?>/script/marked.min.js" type="text/javascript"></script>
<?php include TPLPATH . 'newpage/footer_include.php'; ?>
<script>
var doc = `<?php echo $doc; ?>`;
var menu = `<?php echo $menu; ?>`;
$(function () {
var tops = [];
var scrollType = 0;
var doc = `<?php echo $doc; ?>`;
$('.doc').append(marked.marked(doc));
$('.menu').append(marked.marked(menu));
$('.doc').append(marked.marked(doc));
$('.menu-first').on('click', function () {
$(this).parent().toggleClass('opened');
});
$('.lang').on('mouseenter', function () {
$(this).addClass('opened');
}).on('mouseleave', function () {
$(this).removeClass('opened');
});
if (doc) {
$('.title h1').text($('.doc h1').text());
$('.doc h3').each(function (index, item) {
$('.doc-nav').append('<div><a href="#' + $(item).attr('id') + '">' + item.innerText + '</a></div>');
tops[index] = $(this).position().top;
});
$('.doc-nav a').on('click', function () {
scrollType = 1;
$('.doc-nav a').removeClass('active');
$(this).addClass('active');
}).eq(0).addClass('active');
$('.doc-right').on('scroll', function () {
var height = $(this).innerHeight();
var contentHeight = $('.doc-content').innerHeight() + 64;
var scrollTop = $(this).scrollTop();
var progress = scrollTop / (contentHeight - height) * 100;
var max = 100 * (1 - 28 / 300);
var actual = progress > max ? max : progress;
$('.doc-nav .thumb').css('top', actual + '%');
$('.title h1').css('display', scrollTop > 64 ? 'block' : 'none');
scrollTop > 0 ? $('.header').addClass('shadow') : $('.header').removeClass('shadow');
if (scrollType == 1) {
$(this).scrollTop(scrollTop - 64);
scrollType = 2;
return true;
} else if (scrollType == 2) {
scrollType = 0;
return true;
}
for (var i = 0; i < tops.length - 1; i++) {
var progress2 = tops[i] / contentHeight * 100;
if (progress2 > progress) {
break;
}
}
$('.doc-nav a').removeClass('active');
$('.doc-nav a').eq(i).addClass('active');
});
}
});
</script>
</body>
</html>

View File

@@ -5,6 +5,7 @@
<script src="/static/<?php echo RELEASENUMBER;?>/script/scrollAnimation.js" type="text/javascript"></script>
<script src="/static/vendor/intltel/js/intlTelInput.js"></script>
<script src="/static/vendor/toastr/toastr.js" type="text/javascript"></script>
<script src="/static/<?php echo RELEASENUMBER;?>/script/marked.min.js" type="text/javascript"></script>
<script>
function pregEmail(email) {

View File

@@ -3,11 +3,11 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no minimal-ui">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no minimal-ui">
<meta name="description" content="CodeFever - 轻量级版本控制系统">
<meta name="keywords" content="CodeFever,subversion,git,svn,仓库,项目仓库,代码仓库,版本控制,版本控制系统,版本控制工具,轻量级版本控制系统" />
<link rel="dns-prefetch" href="<?php echo YAML_HOST;?>">
<?php /* <link rel="dns-prefetch" href="<?php echo APPICON_HOST; ?>"> */?>
<?php /* <link rel="dns-prefetch" href="<?php echo APPSCREENSHOT_HOST; ?>"> */?>
@@ -23,6 +23,7 @@
<link href="/static/<?php echo RELEASENUMBER;?>/css/main.css" rel="stylesheet" type="text/css"/>
<link href="/static/<?php echo RELEASENUMBER;?>/css/asset.css" rel="stylesheet" type="text/css"/>
<link href="/static/<?php echo RELEASENUMBER;?>/css/scroll-animation.css" rel="stylesheet" type="text/css"/>
<link href="/static/<?php echo RELEASENUMBER;?>/css/markdown.css" rel="stylesheet" type="text/css"/>
<!-- CORE CSS TEMPLATE - END -->
<link rel="shortcut icon" href="/favicon.ico" />

View File

@@ -25,6 +25,7 @@ div {
/* common */
.bg-F5F8FB { background-color: #f5f8fb; }
.bg-F3F5F6 { background-color: #F3F5F6; }
.bg-EFF3F8 { background-color: #EFF3F8; }
.color-000 { color: #000; };
.color-FFFFFF { color: white; }
@@ -48,6 +49,7 @@ div {
}
.ml-10 { margin-left: 10px; }
.ml-16 { margin-left: 16px; }
.ml-20 { margin-left: 20px; }
.ml-30 { margin-left: 30px; }
.ml-40 { margin-left: 40px; }

View File

@@ -208,4 +208,153 @@ section {
.section-body{
width:90%;
}
}
/* doc */
.doc-left {
border-right: 1px solid #DEE2EC;
}
.doc-left,
.doc-right {
height: 100vh;
overflow: auto;
}
.doc-right {
padding: 0;
}
.doc-logo {
width: 100%;
margin: 22px auto;
}
.switch {
display: inline-block;
border: 4px solid transparent;
border-bottom-color: #2F354D;
border-top: none;
transition: transform .1s;
}
.menu.opened .switch {
transform: rotate(-180deg);
}
.menu .menu-first,
.menu .menu-second > div {
line-height: 32px;
cursor: pointer;
}
.menu .menu-first:hover,
.menu .menu-second > div:hover {
font-weight: bold;
}
.menu .menu-second {
display: none;
}
.menu.opened .menu-second {
display: block;
}
.normal-link {
color: #2F354D !important;
text-decoration: none !important;
}
.menu .normal-link {
display: block;
}
.header {
top: 0px;
z-index: 2;
height: 64px;
position: sticky;
padding: 0px 16px;
background: #fff;
}
.header.shadow {
box-shadow: 0px 10px 30px 0px rgba(66, 72, 86, 0.1);
}
.header .title h1 {
font-size: 20px;
color: #24292F;
font-weight: bold;
display: none;
margin: 0;
}
.header .lang {
width: 96px;
cursor: pointer;
padding: 8px 16px;
margin-right: 64px;
position: relative;
display: inline-block;
}
.header .lang.opened {
color: #3455DB;
}
.lang .lang-menu {
left: 0;
top: 100%;
width: 150%;
display: none;
padding: 8px 0px;
position: absolute;
background: #fff;
box-shadow: 0px 10px 30px 0px rgba(66, 72, 86, 0.1);
}
.lang .switch {
transform: rotate(-180deg);
}
.lang.opened .switch {
transform: none;
border-bottom-color: #3455DB;
}
.lang.opened .lang-menu {
display: block;
}
.lang .lang-menu > div {
line-height: 32px;
padding: 0px 16px;
cursor: pointer;
}
.lang .lang-menu a.normal-link.active {
color: #3455DB !important;
}
.lang .lang-menu > div:hover {
background: #EFF3F8;
}
.doc {
width: calc(100% - 194px);
padding: 0px 64px 64px;
}
.doc-content {
padding: 0px 16px;
}
.doc-nav {
top: 80px;
z-index: 1;
width: 194px;
position: sticky;
padding: 0px 16px;
}
.doc-nav a {
color: #7A859E;
line-height: 28px;
text-decoration: none;
}
.doc-nav a.active,
.doc-nav a:hover {
font-weight: bold;
color: #2F354D;
}
.doc-nav .track {
top: 0;
left: 0;
width: 2px;
height: 300px;
position: absolute;
background: #DEE2EC;
}
.doc-nav .thumb {
top: 0px;
left: 0px;
width: 2px;
height: 28px;
position: absolute;
background: #3455DB;
}

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB