mirror of
https://github.com/BookStackApp/BookStack.git
synced 2026-02-05 08:39:55 +03:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
176a0dcd59 | ||
|
|
94b0f70bfa | ||
|
|
36d7ff77a9 | ||
|
|
fb16ac326f | ||
|
|
5947f59a04 | ||
|
|
1843d80fb7 | ||
|
|
08b2a77d41 | ||
|
|
3e8e9a23cf | ||
|
|
1253711c7d | ||
|
|
963d8f4693 | ||
|
|
0de4d6d223 | ||
|
|
06f694bad2 |
9
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
9
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -35,6 +35,15 @@ body:
|
||||
description: Provide any additional context and screenshots here to help us solve this issue
|
||||
validations:
|
||||
required: false
|
||||
- type: input
|
||||
id: browserdetails
|
||||
attributes:
|
||||
label: Browser Details
|
||||
description: |
|
||||
If this is an issue that occurs when using the BookStack interface, please provide details of the browser used which presents the reported issue.
|
||||
placeholder: (eg. Firefox 97 (64-bit) on Windows 11)
|
||||
validations:
|
||||
required: false
|
||||
- type: input
|
||||
id: bsversion
|
||||
attributes:
|
||||
|
||||
3
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
3
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@@ -33,8 +33,7 @@ body:
|
||||
attributes:
|
||||
label: Have you searched for an existing open/closed issue?
|
||||
description: |
|
||||
To help us keep these issues under control, please ensure you have first [searched our issue list](https://github.com/BookStackApp/BookStack/issues?q=is%3Aissue)
|
||||
for any existing issues that cover the fundemental benefit/goal of your request.
|
||||
To help us keep these issues under control, please ensure you have first [searched our issue list](https://github.com/BookStackApp/BookStack/issues?q=is%3Aissue) for any existing issues that cover the fundemental benefit/goal of your request.
|
||||
options:
|
||||
- label: I have searched for existing issues and none cover my fundemental request
|
||||
required: true
|
||||
|
||||
@@ -239,6 +239,9 @@ class PageContent
|
||||
$html .= $doc->saveHTML($childNode);
|
||||
}
|
||||
|
||||
// Perform required string-level tweaks
|
||||
$html = str_replace(' ', ' ', $html);
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
|
||||
6
public/dist/app.js
vendored
6
public/dist/app.js
vendored
File diff suppressed because one or more lines are too long
2
public/dist/export-styles.css
vendored
2
public/dist/export-styles.css
vendored
File diff suppressed because one or more lines are too long
2
public/dist/styles.css
vendored
2
public/dist/styles.css
vendored
File diff suppressed because one or more lines are too long
@@ -63,7 +63,7 @@ Below is a high-level road map view for BookStack to provide a sense of directio
|
||||
|
||||
- **Platform REST API** - *(Most actions implemented, maturing)*
|
||||
- *A REST API covering, at minimum, control of core content models (Books, Chapters, Pages) for automation and platform extension.*
|
||||
- **Editor Alignment & Review** - *(Started)*
|
||||
- **Editor Alignment & Review** - *(In Progress)*
|
||||
- *Review the page editors with goal of achieving increased interoperability & feature parity while also considering collaborative editing potential.*
|
||||
- **Permission System Review**
|
||||
- *Improvement in how permissions are applied and a review of the efficiency of the permission & roles system.*
|
||||
|
||||
@@ -59,12 +59,10 @@ class CodeEditor {
|
||||
this.languageInput.value = language;
|
||||
this.callback = callback;
|
||||
|
||||
this.show();
|
||||
this.updateEditorMode(language);
|
||||
|
||||
window.importVersioned('code').then(Code => {
|
||||
Code.setContent(this.editor, code);
|
||||
});
|
||||
this.show()
|
||||
.then(() => this.updateEditorMode(language))
|
||||
.then(() => window.importVersioned('code'))
|
||||
.then(Code => Code.setContent(this.editor, code));
|
||||
}
|
||||
|
||||
async show() {
|
||||
|
||||
@@ -221,11 +221,15 @@ export function build(options) {
|
||||
// Build toolbar content
|
||||
const {toolbar, groupButtons: toolBarGroupButtons} = buildToolbar(options);
|
||||
|
||||
// BookStack Version
|
||||
const version = document.querySelector('script[src*="/dist/app.js"]').getAttribute('src').split('?version=')[1];
|
||||
|
||||
// Return config object
|
||||
return {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
selector: '#html-editor',
|
||||
cache_suffix: '?version=' + version,
|
||||
content_css: [
|
||||
window.baseUrl('/dist/styles.css'),
|
||||
],
|
||||
@@ -239,6 +243,7 @@ export function build(options) {
|
||||
remove_script_host: false,
|
||||
document_base_url: window.baseUrl('/'),
|
||||
end_container_on_empty_block: true,
|
||||
remove_trailing_brs: false,
|
||||
statusbar: false,
|
||||
menubar: false,
|
||||
paste_data_images: false,
|
||||
|
||||
@@ -91,15 +91,35 @@ function defineCodeBlockCustomElement(editor) {
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
const connectedTime = Date.now();
|
||||
if (this.cm) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.cleanChildContent();
|
||||
|
||||
const container = this.shadowRoot.querySelector('.CodeMirrorContainer');
|
||||
importVersioned('code').then(Code => {
|
||||
const renderCodeMirror = (Code) => {
|
||||
this.cm = Code.wysiwygView(container, this.getContent(), this.getLanguage());
|
||||
Code.updateLayout(this.cm);
|
||||
};
|
||||
|
||||
window.importVersioned('code').then((Code) => {
|
||||
const timeout = (Date.now() - connectedTime < 20) ? 20 : 0;
|
||||
setTimeout(() => renderCodeMirror(Code), timeout);
|
||||
});
|
||||
}
|
||||
|
||||
cleanChildContent() {
|
||||
const pre = this.querySelector('pre');
|
||||
if (!pre) return;
|
||||
|
||||
for (const preChild of pre.childNodes) {
|
||||
if (preChild.nodeName === '#text' && preChild.textContent === '') {
|
||||
preChild.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
win.customElements.define('code-block', CodeBlockElement);
|
||||
@@ -130,15 +150,13 @@ function register(editor, url) {
|
||||
} else {
|
||||
const textContent = editor.selection.getContent({format: 'text'});
|
||||
showPopup(editor, textContent, '', (newCode, newLang) => {
|
||||
const wrap = doc.createElement('code-block');
|
||||
const pre = doc.createElement('pre');
|
||||
const code = doc.createElement('code');
|
||||
code.classList.add(`language-${newLang}`);
|
||||
code.innerText = newCode;
|
||||
pre.append(code);
|
||||
wrap.append(pre);
|
||||
|
||||
editor.insertContent(wrap.outerHTML);
|
||||
editor.insertContent(pre.outerHTML);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -168,7 +186,7 @@ function register(editor, url) {
|
||||
|
||||
editor.parser.addNodeFilter('code-block', function(elms) {
|
||||
for (const el of elms) {
|
||||
el.attr('content-editable', 'false');
|
||||
el.attr('contenteditable', 'false');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -131,12 +131,12 @@ return [
|
||||
'open_link' => 'Apri collegamento in...',
|
||||
'open_link_current' => 'Finestra corrente',
|
||||
'open_link_new' => 'Nuova finestra',
|
||||
'insert_collapsible' => 'Insert collapsible block',
|
||||
'collapsible_unwrap' => 'Unwrap',
|
||||
'edit_label' => 'Edit label',
|
||||
'toggle_open_closed' => 'Toggle open/closed',
|
||||
'collapsible_edit' => 'Edit collapsible block',
|
||||
'toggle_label' => 'Toggle label',
|
||||
'insert_collapsible' => 'Inserisci blocco collassabile',
|
||||
'collapsible_unwrap' => 'Espandi',
|
||||
'edit_label' => 'Modifica etichetta',
|
||||
'toggle_open_closed' => 'Espandi/Comprimi',
|
||||
'collapsible_edit' => 'Modifica blocco collassabile',
|
||||
'toggle_label' => 'Attiva/Disattiva etichetta',
|
||||
|
||||
// About view
|
||||
'about_title' => 'Informazioni sull\'editor di WYSIWYG',
|
||||
|
||||
@@ -57,7 +57,7 @@ return [
|
||||
'list_numbered' => '有序列表',
|
||||
'indent_increase' => '增加缩进',
|
||||
'indent_decrease' => '减少缩进',
|
||||
'table' => '表',
|
||||
'table' => '表格',
|
||||
'insert_image' => '插入图片',
|
||||
'insert_image_title' => '插入/编辑图片',
|
||||
'insert_link' => '插入/编辑链接',
|
||||
|
||||
@@ -238,13 +238,13 @@
|
||||
}
|
||||
|
||||
.fade-in-when-active {
|
||||
opacity: 0.6;
|
||||
@include lightDark(opacity, 0.6, 0.7);
|
||||
transition: opacity ease-in-out 120ms;
|
||||
&:hover, &:focus-within {
|
||||
opacity: 1;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
@media (prefers-contrast: more) {
|
||||
opacity: 1;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -361,16 +361,13 @@ body.flexbox {
|
||||
display: none;
|
||||
}
|
||||
.tri-layout-left-contents > *, .tri-layout-right-contents > * {
|
||||
opacity: 0.6;
|
||||
@include lightDark(opacity, 0.6, 0.7);
|
||||
transition: opacity ease-in-out 120ms;
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
&:focus-within {
|
||||
opacity: 1;
|
||||
&:hover, &:focus-within {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
@media (prefers-contrast: more) {
|
||||
opacity: 1;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -193,7 +193,7 @@
|
||||
}
|
||||
}
|
||||
.entity-list-item.selected {
|
||||
background-color: rgba(0, 0, 0, 0.08);
|
||||
@include lightDark(background-color, rgba(0, 0, 0, 0.08), rgba(255, 255, 255, 0.08));
|
||||
}
|
||||
.entity-list-item.no-hover {
|
||||
margin-top: -$-xs;
|
||||
|
||||
@@ -164,6 +164,10 @@ body.tox-fullscreen, body.markdown-fullscreen {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
p:empty {
|
||||
min-height: 1.6em;
|
||||
}
|
||||
|
||||
&.page-revision {
|
||||
pre code {
|
||||
white-space: pre-wrap;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@extends('layouts.base')
|
||||
|
||||
@section('head')
|
||||
<script src="{{ url('/libs/tinymce/tinymce.min.js?ver=4.9.4') }}" nonce="{{ $cspNonce }}"></script>
|
||||
<script src="{{ url('/libs/tinymce/tinymce.min.js?ver=5.10.2') }}" nonce="{{ $cspNonce }}"></script>
|
||||
@stop
|
||||
|
||||
@section('body-class', 'flexbox')
|
||||
|
||||
@@ -692,35 +692,43 @@ class PageContentTest extends TestCase
|
||||
|
||||
public function test_base64_images_within_markdown_blanked_if_not_supported_extension_for_extract()
|
||||
{
|
||||
$this->asEditor();
|
||||
$page = Page::query()->first();
|
||||
|
||||
$this->put($page->getUrl(), [
|
||||
$this->asEditor()->put($page->getUrl(), [
|
||||
'name' => $page->name, 'summary' => '',
|
||||
'markdown' => 'test ',
|
||||
]);
|
||||
|
||||
$page->refresh();
|
||||
$this->assertStringContainsString('<img src=""', $page->html);
|
||||
$this->assertStringContainsString('<img src=""', $page->refresh()->html);
|
||||
}
|
||||
|
||||
public function test_nested_headers_gets_assigned_an_id()
|
||||
{
|
||||
$this->asEditor();
|
||||
$page = Page::query()->first();
|
||||
|
||||
$content = '<table><tbody><tr><td><h5>Simple Test</h5></td></tr></tbody></table>';
|
||||
$this->put($page->getUrl(), [
|
||||
$this->asEditor()->put($page->getUrl(), [
|
||||
'name' => $page->name,
|
||||
'html' => $content,
|
||||
'summary' => '',
|
||||
]);
|
||||
|
||||
$updatedPage = Page::query()->where('id', '=', $page->id)->first();
|
||||
|
||||
// The top level <table> node will get assign the bkmrk-simple-test id because the system will
|
||||
// take the node value of h5
|
||||
// So the h5 should get the bkmrk-simple-test-1 id
|
||||
$this->assertStringContainsString('<h5 id="bkmrk-simple-test-1">Simple Test</h5>', $updatedPage->html);
|
||||
$this->assertStringContainsString('<h5 id="bkmrk-simple-test-1">Simple Test</h5>', $page->refresh()->html);
|
||||
}
|
||||
|
||||
public function test_non_breaking_spaces_are_preserved()
|
||||
{
|
||||
/** @var Page $page */
|
||||
$page = Page::query()->first();
|
||||
|
||||
$content = '<p> </p>';
|
||||
$this->asEditor()->put($page->getUrl(), [
|
||||
'name' => $page->name,
|
||||
'html' => $content,
|
||||
]);
|
||||
|
||||
$this->assertStringContainsString('<p id="bkmrk-%C2%A0"> </p>', $page->refresh()->html);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user