mirror of
https://github.com/PGYER/codefever.git
synced 2026-06-01 06:29:23 +08:00
feat: codefever-community documentation system
This commit is contained in:
@@ -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)) {
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -7,3 +7,4 @@ $lang['base_error_message_tips'] = '抱歉,请重新尝试访问网站,或
|
||||
$lang['base_go_home'] = '返回主页';
|
||||
$lang['base_go_prepage'] = '返回上一页';
|
||||
$lang['base_confirm'] = '确定';
|
||||
$lang['base_directory'] = '目录';
|
||||
|
||||
@@ -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>
|
||||
@@ -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) {
|
||||
|
||||
@@ -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" />
|
||||
@@ -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; }
|
||||
|
||||
@@ -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
BIN
www/static/images/logo-community-doc.png
Normal file
BIN
www/static/images/logo-community-doc.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
Reference in New Issue
Block a user