- Removed old 'editor-*-update' commands to instead use the aligned
'editor::replace' command that we already have.
- Changed the way custom styles are loaded for the WYSIWYG editor so we
don't need an API call but instead scape content from the parent page
header using comments as identifiers. Added tests to ensure comments
exist and align.
return view('home.default', $commonData);
}
return view('home.default', $commonData);
}
- /**
- * Get custom head HTML, Used in ajax calls to show in editor.
- */
- public function customHeadContent()
- {
- return view('common.custom-head');
- }
-
/**
* Show the view for /robots.txt.
*/
/**
* Show the view for /robots.txt.
*/
toolbarLabel.closest('.markdown-editor-wrap').classList.add('active');
});
toolbarLabel.closest('.markdown-editor-wrap').classList.add('active');
});
- window.$events.listen('editor-markdown-update', value => {
- this.cm.setValue(value);
- this.updateAndRender();
- });
-
this.codeMirrorSetup();
this.listenForBookStackEditorEvents();
this.codeMirrorSetup();
this.listenForBookStackEditorEvents();
this.draftDisplay.innerText = this.editingPageText;
this.toggleDiscardDraftVisibility(false);
this.draftDisplay.innerText = this.editingPageText;
this.toggleDiscardDraftVisibility(false);
- window.$events.emit('editor-html-update', response.data.html || '');
- window.$events.emit('editor-markdown-update', response.data.markdown || response.data.html);
+ window.$events.emit('editor::replace', {
+ html: response.data.html,
+ markdown: response.data.markdown,
+ });
this.titleElem.value = response.data.name;
window.setTimeout(() => {
this.titleElem.value = response.data.name;
window.setTimeout(() => {
- * Load custom HTML head content from the settings into the editor.
- * TODO: We should be able to get this from current parent page?
- * @param {Editor} editor
+ * Fetch custom HTML head content from the parent page head into the editor.
-function loadCustomHeadContent(editor) {
- window.$http.get(window.baseUrl('/custom-head-content')).then(resp => {
- if (!resp.data) return;
- let head = editor.getDoc().querySelector('head');
- head.innerHTML += resp.data;
- });
+function fetchCustomHeadContent() {
+ const headContentLines = document.head.innerHTML.split("\n");
+ const startLineIndex = headContentLines.findIndex(line => line.trim() === '<!-- Start: custom user content -->');
+ const endLineIndex = headContentLines.findIndex(line => line.trim() === '<!-- End: custom user content -->');
+ if (startLineIndex === -1 || endLineIndex === -1) {
+ return ''
+ }
+ return headContentLines.slice(startLineIndex + 1, endLineIndex).join('\n');
window.$events.emit('editor-html-change', content);
}
window.$events.emit('editor-html-change', content);
}
- // TODO - Update to standardise across both editors
- // Use events within listenForBookStackEditorEvents instead (Different event signature)
- window.$events.listen('editor-html-update', html => {
- editor.setContent(html);
- editor.selection.select(editor.getBody(), true);
- editor.selection.collapse(false);
- editorChange(html);
- });
-
// Custom handler hook
window.$events.emitPublic(options.containerElement, 'editor-tinymce::setup', {editor});
// Custom handler hook
window.$events.emitPublic(options.containerElement, 'editor-tinymce::setup', {editor});
}
},
init_instance_callback(editor) {
}
},
init_instance_callback(editor) {
- loadCustomHeadContent(editor);
+ let head = editor.getDoc().querySelector('head');
+ console.log(fetchCustomHeadContent());
+ head.innerHTML += fetchCustomHeadContent();
},
setup(editor) {
for (const [key, config] of Object.entries(toolBarGroupButtons)) {
},
setup(editor) {
for (const [key, config] of Object.entries(toolBarGroupButtons)) {
@inject('headContent', 'BookStack\Theming\CustomHtmlHeadContentProvider')
@if(setting('app-custom-head') && \Route::currentRouteName() !== 'settings')
@inject('headContent', 'BookStack\Theming\CustomHtmlHeadContentProvider')
@if(setting('app-custom-head') && \Route::currentRouteName() !== 'settings')
-<!-- Custom user content -->
+<!-- Start: custom user content -->
{!! $headContent->forWeb() !!}
{!! $headContent->forWeb() !!}
-<!-- End custom user content -->
+<!-- End: custom user content -->
@endif
\ No newline at end of file
@endif
\ No newline at end of file
// Other Pages
Route::get('/', [HomeController::class, 'index']);
Route::get('/home', [HomeController::class, 'index']);
// Other Pages
Route::get('/', [HomeController::class, 'index']);
Route::get('/home', [HomeController::class, 'index']);
- Route::get('/custom-head-content', [HomeController::class, 'customHeadContent']);
// Settings
Route::get('/settings', [SettingController::class, 'index'])->name('settings');
// Settings
Route::get('/settings', [SettingController::class, 'index'])->name('settings');
$resp->assertSee('console.log("cat")', false);
}
$resp->assertSee('console.log("cat")', false);
}
+ public function test_content_wrapped_in_specific_html_comments()
+ {
+ // These comments are used to identify head content for editor injection
+ $this->setSettings(['app-custom-head' => '<script>console.log("cat");</script>']);
+ $resp = $this->get('/login');
+ $resp->assertSee('<!-- Start: custom user content -->', false);
+ $resp->assertSee('<!-- End: custom user content -->', false);
+ }
+
public function test_configured_content_does_not_show_on_settings_page()
{
$this->setSettings(['app-custom-head' => '<script>console.log("cat");</script>']);
public function test_configured_content_does_not_show_on_settings_page()
{
$this->setSettings(['app-custom-head' => '<script>console.log("cat");</script>']);