@@ -106,6 +106,16 @@ $(function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('.markdown-body :header').prepend(function() {
|
||||||
|
$(this).prepend('<a class="anchor" href="#'+$(this).attr('id')+'"><i class="fas fa-link"></i>');
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.markdown-body :header').hover(function(){
|
||||||
|
$(this).find('a.anchor').show();
|
||||||
|
}, function(){
|
||||||
|
$(this).find('a.anchor').hide();
|
||||||
|
});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
$('input').iCheck({
|
$('input').iCheck({
|
||||||
checkboxClass: 'icheckbox_square-blue',
|
checkboxClass: 'icheckbox_square-blue',
|
||||||
|
|||||||
@@ -37,3 +37,4 @@ footer.main-footer {
|
|||||||
@import 'calendar';
|
@import 'calendar';
|
||||||
@import 'dashboard';
|
@import 'dashboard';
|
||||||
@import 'navbar';
|
@import 'navbar';
|
||||||
|
@import 'documentation';
|
||||||
|
|||||||
25
assets/sass/documentation.scss
Normal file
25
assets/sass/documentation.scss
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Kimai time-tracking app.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.markdown-body {
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
a.anchor {
|
||||||
|
float: left;
|
||||||
|
font-size: 0.5em;
|
||||||
|
margin-left: -1em;
|
||||||
|
padding-top: 0.5em;
|
||||||
|
color: $text-color;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: $screen-sm-min) {
|
||||||
|
.markdown-body {
|
||||||
|
padding-left: 25px;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* The filter form is available on most pages above the datatable */
|
/* The filter form is available on most pages above the datatable */
|
||||||
@media (min-width: 768px) {
|
@media (min-width: $screen-sm-min) {
|
||||||
.toolbar {
|
.toolbar {
|
||||||
form.navbar-form {
|
form.navbar-form {
|
||||||
font-size: $font-size-base;
|
font-size: $font-size-base;
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"build/app.js": "/build/app.js?3dadf2331143d4cac84f",
|
"build/app.js": "/build/app.js?d823754f6c3293656052",
|
||||||
"build/app.css": "/build/app.css?6501689dff217d14b179e3049295343e",
|
"build/app.css": "/build/app.css?979d88ed847886068fcf3eb0bc3de545",
|
||||||
"build/images/blue@2x.png": "/build/images/blue@2x.png?2694acfd",
|
"build/images/blue@2x.png": "/build/images/blue@2x.png?2694acfd",
|
||||||
"build/images/blue.png": "/build/images/blue.png?96f8a905",
|
"build/images/blue.png": "/build/images/blue.png?96f8a905",
|
||||||
"build/fonts/fa-solid-900.woff2": "/build/fonts/fa-solid-900.woff2?e8a92a29",
|
"build/fonts/fa-solid-900.woff2": "/build/fonts/fa-solid-900.woff2?e8a92a29",
|
||||||
|
|||||||
@@ -9,8 +9,6 @@
|
|||||||
|
|
||||||
namespace App\Utils;
|
namespace App\Utils;
|
||||||
|
|
||||||
use Parsedown as MarkdownParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple class to parse markdown syntax and return HTML.
|
* A simple class to parse markdown syntax and return HTML.
|
||||||
*/
|
*/
|
||||||
@@ -26,7 +24,7 @@ class Markdown
|
|||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->parser = new MarkdownParser();
|
$this->parser = new ParsedownExtension();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
68
src/Utils/ParsedownExtension.php
Normal file
68
src/Utils/ParsedownExtension.php
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Kimai time-tracking app.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This Class extends the default Parsedown Class for custom methods.
|
||||||
|
*/
|
||||||
|
class ParsedownExtension extends \Parsedown
|
||||||
|
{
|
||||||
|
private $ids = [];
|
||||||
|
|
||||||
|
protected function blockHeader($line)
|
||||||
|
{
|
||||||
|
$block = parent::blockHeader($line);
|
||||||
|
|
||||||
|
$text = $block['element']['text'];
|
||||||
|
$id = $this->getIDfromText($text);
|
||||||
|
|
||||||
|
// add id-attribute
|
||||||
|
$block['element']['attributes'] = [
|
||||||
|
'id' => $id
|
||||||
|
];
|
||||||
|
|
||||||
|
return $block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* github-action for creating ids:
|
||||||
|
*
|
||||||
|
* - It downcases the header string
|
||||||
|
* - remove anything that is not a letter, number, space or hyphen
|
||||||
|
* - changes any space to a hyphen.
|
||||||
|
* - If that is not unique, add "-1", "-2", "-3",... to make it unique
|
||||||
|
*
|
||||||
|
* @param $text
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function getIDfromText($text)
|
||||||
|
{
|
||||||
|
$text = strtolower($text);
|
||||||
|
|
||||||
|
$text = preg_replace('/[^A-Za-z0-9\-\ ]/', '', $text);
|
||||||
|
$text = strtr($text, [' ' => '-']);
|
||||||
|
|
||||||
|
if (isset($this->ids[$text])) {
|
||||||
|
$i = 0;
|
||||||
|
$numberedText = $text . '-1';
|
||||||
|
|
||||||
|
while (isset($this->ids[$numberedText])) {
|
||||||
|
$i++;
|
||||||
|
$numberedText = $text . '-' . $i;
|
||||||
|
}
|
||||||
|
|
||||||
|
$text = $numberedText;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->ids[$text] = '';
|
||||||
|
|
||||||
|
return $text;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
<a href="{{ path('help') }}">{{ 'action.back'|trans }}</a>
|
<a href="{{ path('help') }}">{{ 'action.back'|trans }}</a>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="box-body">
|
<div class="box-body markdown-body">
|
||||||
{{ documentation|md2html|replace(replacer)|raw }}
|
{{ documentation|md2html|replace(replacer)|raw }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class HelpControllerTest extends ControllerBaseTest
|
|||||||
$client = $this->getClientForAuthenticatedUser();
|
$client = $this->getClientForAuthenticatedUser();
|
||||||
$this->request($client, '/help/');
|
$this->request($client, '/help/');
|
||||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||||
$this->assertContains('<h1>Kimai documentation</h1>', $client->getResponse()->getContent());
|
$this->assertContains('<h1 id="kimai-documentation">Kimai documentation</h1>', $client->getResponse()->getContent());
|
||||||
$this->assertContains('<a href="configurations">', $client->getResponse()->getContent());
|
$this->assertContains('<a href="configurations">', $client->getResponse()->getContent());
|
||||||
$this->assertContains('<a href="developers">', $client->getResponse()->getContent());
|
$this->assertContains('<a href="developers">', $client->getResponse()->getContent());
|
||||||
$this->assertContains('<a href="users">', $client->getResponse()->getContent());
|
$this->assertContains('<a href="users">', $client->getResponse()->getContent());
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class MarkdownExtensionTest extends TestCase
|
|||||||
{
|
{
|
||||||
$sut = new MarkdownExtension(new Markdown());
|
$sut = new MarkdownExtension(new Markdown());
|
||||||
$this->assertEquals('<p><em>test</em></p>', $sut->markdownToHtml('*test*'));
|
$this->assertEquals('<p><em>test</em></p>', $sut->markdownToHtml('*test*'));
|
||||||
$this->assertEquals('<h1>foobar</h1>', $sut->markdownToHtml('# foobar'));
|
$this->assertEquals('<h1 id="foobar">foobar</h1>', $sut->markdownToHtml('# foobar'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testTimesheetContent()
|
public function testTimesheetContent()
|
||||||
|
|||||||
@@ -21,6 +21,6 @@ class MarkdownTest extends TestCase
|
|||||||
{
|
{
|
||||||
$sut = new Markdown();
|
$sut = new Markdown();
|
||||||
$this->assertEquals('<p><em>test</em></p>', $sut->toHtml('*test*'));
|
$this->assertEquals('<p><em>test</em></p>', $sut->toHtml('*test*'));
|
||||||
$this->assertEquals('<h1>foobar</h1>', $sut->toHtml('# foobar'));
|
$this->assertEquals('<h1 id="foobar">foobar</h1>', $sut->toHtml('# foobar'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user