Closes #11294: Markdown Preview (#11894)

* MarkdownWidget

* Change border and color of active markdown tab

* Fix template name typo

* Add render markdown endpoint

* Static assets for markdown widget

* widget style fix and unique ids based on name

* Replace SmallTextArea with SmallMarkdownWidget

* Clear innerHTML before swapping

* render markdown directly in template

* change render markdown view path

* remove small markdown widget

* Simplify rendering logic

* Use a form to clean input Markdown data

---------

Co-authored-by: Jeremy Stretch <jstretch@ns1.com>
This commit is contained in:
Aron Bergur Jóhannsson
2023-03-09 13:21:13 +00:00
committed by GitHub
parent 33286aad39
commit fa60f9d2a8
22 changed files with 150 additions and 58 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -4,6 +4,7 @@ import { initMoveButtons } from './moveOptions';
import { initReslug } from './reslug';
import { initSelectAll } from './selectAll';
import { initSelectMultiple } from './selectMultiple';
import { initMarkdownPreviews } from './markdownPreview';
export function initButtons(): void {
for (const func of [
@@ -13,6 +14,7 @@ export function initButtons(): void {
initSelectAll,
initSelectMultiple,
initMoveButtons,
initMarkdownPreviews,
]) {
func();
}

View File

@@ -0,0 +1,45 @@
import { isTruthy } from 'src/util';
/**
* interface for htmx configRequest event
*/
declare global {
interface HTMLElementEventMap {
'htmx:configRequest': CustomEvent<{
parameters: Record<string, string>;
headers: Record<string, string>;
}>;
}
}
function initMarkdownPreview(markdownWidget: HTMLDivElement) {
const previewButton = markdownWidget.querySelector('button.preview-button') as HTMLButtonElement;
const textarea = markdownWidget.querySelector('textarea') as HTMLTextAreaElement;
const preview = markdownWidget.querySelector('div.preview') as HTMLDivElement;
/**
* Make sure the textarea has style attribute height
* So that it can be copied over to preview div.
*/
if (!isTruthy(textarea.style.height)) {
const { height } = textarea.getBoundingClientRect();
textarea.style.height = `${height}px`;
}
/**
* Add the value of the textarea to the body of the htmx request
* and copy the height of text are to the preview div
*/
previewButton.addEventListener('htmx:configRequest', e => {
e.detail.parameters = { text: textarea.value || '' };
e.detail.headers['X-CSRFToken'] = window.CSRF_TOKEN;
preview.style.minHeight = textarea.style.height;
preview.innerHTML = '';
});
}
export function initMarkdownPreviews(): void {
for (const markdownWidget of document.querySelectorAll<HTMLDivElement>('.markdown-widget')) {
initMarkdownPreview(markdownWidget);
}
}

View File

@@ -236,12 +236,12 @@ table {
}
th.asc > a::after {
content: "\f0140";
content: '\f0140';
font-family: 'Material Design Icons';
}
th.desc > a::after {
content: "\f0143";
content: '\f0143';
font-family: 'Material Design Icons';
}
@@ -416,18 +416,18 @@ nav.search {
}
}
// Styles for the quicksearch and its clear button;
// Styles for the quicksearch and its clear button;
// Overrides input-group styles and adds transition effects
.quicksearch {
input[type="search"] {
border-radius: $border-radius !important;
input[type='search'] {
border-radius: $border-radius !important;
}
button {
margin-left: -32px !important;
z-index: 100 !important;
outline: none !important;
border-radius: $border-radius !important;
border-radius: $border-radius !important;
transition: visibility 0s, opacity 0.2s linear;
}
@@ -998,9 +998,24 @@ div.card-overlay {
padding: 8px;
}
/* Markdown widget */
.markdown-widget {
.nav-link {
border-bottom: 0;
&.active {
background-color: var(--nbx-body-bg);
}
}
.nav-tabs {
background-color: var(--nbx-pre-bg);
}
}
// Preformatted text blocks
td pre {
margin-bottom: 0
margin-bottom: 0;
}
pre.block {
padding: $spacer;