Skip to content

Commit

Permalink
fix: Fix collection description (#2065)
Browse files Browse the repository at this point in the history
Fixes #2064

### Changes

- Switches MDE library to one that supports shadow DOM
- Refactors collection components to btrix components
- Fixes collection detail not expanding and contracting correctly
  • Loading branch information
SuaYoo committed Sep 6, 2024
1 parent 4c36c80 commit b4e34d1
Show file tree
Hide file tree
Showing 9 changed files with 828 additions and 732 deletions.
4 changes: 4 additions & 0 deletions docs/user-guide/collection.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

You can create a collection from the Collections page, or the _Create New ..._ shortcut from the org overview.

## Collection Description

The description can be formatted with basic [Markdown](https://github.github.com/gfm/#what-is-markdown-) syntax to include headings, bolded and italicized text, lists, and links. The editor is powered by [ink-mde](https://github.com/davidmyersdev/ink-mde), an open source Markdown editor.

## Sharing Collections

Collections are private by default, but can be made public by marking them as sharable in the Metadata step of collection creation, or by toggling the _Collection is Shareable_ switch in the share collection dialogue.
Expand Down
2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
"@types/sinon": "^10.0.6",
"@typescript-eslint/eslint-plugin": "^6.20.0",
"@typescript-eslint/parser": "^6.20.0",
"@wysimark/standalone": "3.0.20",
"@xstate/fsm": "^1.6.2",
"@zxcvbn-ts/core": "^3.0.4",
"@zxcvbn-ts/language-common": "^3.0.4",
Expand Down Expand Up @@ -49,6 +48,7 @@
"html-loader": "^3.0.1",
"html-webpack-plugin": "^5.5.0",
"immutable": "^4.1.0",
"ink-mde": "~0.33.0",
"iso-639-1": "^2.1.15",
"lit": "3.1.1",
"lit-shared-state": "^0.2.1",
Expand Down
232 changes: 144 additions & 88 deletions frontend/src/components/ui/markdown-editor.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// cSpell:words wysimark

import { createWysimark } from "@wysimark/standalone";
import { html, LitElement, type PropertyValues } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { guard } from "lit/directives/guard.js";
import { msg, str } from "@lit/localize";
import { wrap, type AwaitableInstance } from "ink-mde";
import { css, html, type PropertyValues } from "lit";
import { customElement, property, query } from "lit/decorators.js";

import { TailwindElement } from "@/classes/TailwindElement";
import { getHelpText } from "@/utils/form";
import { formatNumber } from "@/utils/localization";

type MarkdownChangeDetail = {
value: string;
Expand All @@ -15,116 +15,172 @@ export type MarkdownChangeEvent = CustomEvent<MarkdownChangeDetail>;
/**
* Edit and preview text in markdown
*
* @event on-change MarkdownChangeEvent
* @fires btrix-change MarkdownChangeEvent
*/
@customElement("btrix-markdown-editor")
export class MarkdownEditor extends LitElement {
export class MarkdownEditor extends TailwindElement {
static styles = css`
:host {
--ink-border-radius: var(--sl-input-border-radius-medium);
--ink-color: var(--sl-input-color);
--ink-block-background-color: var(--sl-color-neutral-50);
--ink-block-padding: var(--sl-input-spacing-small);
}
.ink-mde {
border: solid var(--sl-input-border-width) var(--sl-input-border-color);
}
.ink-mde-toolbar {
border-top-left-radius: var(--ink-border-radius);
border-top-right-radius: var(--ink-border-radius);
border-bottom: 1px solid var(--sl-panel-border-color);
}
.ink-mde .ink-mde-toolbar .ink-button {
width: 2rem;
height: 2rem;
}
/* TODO check why style wasn't applied */
.cm-announced {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
`;

@property({ type: String })
label = "";

@property({ type: String })
initialValue = "";

@property({ type: String })
name = "markdown";
value = "";

@property({ type: Number })
maxlength?: number;

@state()
value = "";
@query("#editor-textarea")
private readonly textarea?: HTMLTextAreaElement | null;

createRenderRoot() {
// Disable shadow DOM for styles to work
return this;
private editor?: AwaitableInstance;

public checkValidity() {
return this.textarea?.checkValidity();
}

protected updated(changedProperties: PropertyValues<this>) {
if (changedProperties.has("initialValue") && this.initialValue) {
protected willUpdate(changedProperties: PropertyValues<this>): void {
if (
changedProperties.has("initialValue") &&
this.initialValue &&
!this.value
) {
this.value = this.initialValue;
this.initEditor();
}
}

disconnectedCallback(): void {
super.disconnectedCallback();
this.editor?.destroy();
}

protected firstUpdated(): void {
if (!this.initialValue) {
this.initEditor();
}
this.initEditor();
}

render() {
const isInvalid = this.maxlength && this.value.length > this.maxlength;
return html`
<fieldset
class="markdown-editor-wrapper with-max-help-text"
?data-invalid=${isInvalid}
?data-user-invalid=${isInvalid}
>
<input name=${this.name} type="hidden" value="${this.value}" />
${guard(
[this.initialValue],
() => html`
<style>
.markdown-editor-wrapper[data-user-invalid] {
--select-editor-color: var(--sl-color-danger-400);
}
.markdown-editor-wrapper[data-user-invalid]
.markdown-editor
> div {
border: 1px solid var(--sl-color-danger-400);
}
.markdown-editor {
--blue-100: var(--sl-color-blue-100);
}
/* NOTE wysimark doesn't support customization or
a way of selecting elements as of 2.2.15
https://github.com/portive/wysimark/issues/10 */
/* Editor container: */
.markdown-editor > div {
overflow: hidden;
border-radius: var(--sl-input-border-radius-medium);
font-family: var(--sl-font-sans);
font-size: 1rem;
}
/* Hide unsupported button features */
/* Table, images: */
.markdown-editor > div > div > div > div:nth-child(9),
.markdown-editor > div > div > div > div:nth-child(10) {
display: none !important;
}
.markdown-editor div[role="textbox"] {
font-size: var(--sl-font-size-medium);
padding: var(--sl-spacing-small) var(--sl-spacing-medium);
}
</style>
<div class="markdown-editor font-sm"></div>
`,
)}
${this.maxlength
? html`<div class="form-help-text">
${getHelpText(this.maxlength, this.value.length)}
</div>`
: ""}
<fieldset ?data-invalid=${isInvalid} ?data-user-invalid=${isInvalid}>
<label class="form-label">${this.label}</label>
<textarea id="editor-textarea"></textarea>
<div class="helpText flex items-baseline justify-between">
<p class="text-xs">
${msg(
html`Supports
<a
class="text-blue-500 hover:text-blue-600"
href="https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax"
target="_blank"
rel="noopener noreferrer nofollow"
>GitHub Flavored Markdown</a
>.`,
)}
</p>
${this.maxlength
? html`<div>
<p class="form-help-text">
${getHelpText(this.maxlength, this.value.length)}
</p>
</div>`
: ""}
</div>
</fieldset>
`;
}

private initEditor() {
const editor = createWysimark(this.querySelector(".markdown-editor")!, {
initialMarkdown: this.initialValue,
minHeight: "12rem",
onChange: async () => {
const value = editor.getMarkdown();
const input = this.querySelector<HTMLTextAreaElement>(
`input[name=${this.name}]`,
);
input!.value = value;
this.value = value;
await this.updateComplete;
this.dispatchEvent(
new CustomEvent<MarkdownChangeDetail>("on-change", {
detail: {
value: value,
},
}),
);
if (!this.textarea) return;

if (this.editor) {
this.editor.destroy();
}

this.editor = wrap(this.textarea, {
doc: this.initialValue,
hooks: {
beforeUpdate: (doc: string) => {
if (this.maxlength) {
this.textarea?.setCustomValidity(
doc.length > this.maxlength
? msg(
str`Please shorten the description to ${formatNumber(this.maxlength)} or fewer characters.`,
)
: "",
);
}
},
afterUpdate: async (doc: string) => {
this.value = doc;

await this.updateComplete;
this.dispatchEvent(
new CustomEvent<MarkdownChangeDetail>("btrix-change", {
detail: {
value: doc,
},
}),
);
},
},
interface: {
appearance: "light",
attribution: false,
autocomplete: false,
toolbar: true,
},
toolbar: {
bold: true,
code: false,
codeBlock: false,
heading: true,
image: false,
italic: true,
link: true,
list: true,
orderedList: true,
quote: false,
taskList: false,
upload: false,
},
});
}
Expand Down
Loading

0 comments on commit b4e34d1

Please sign in to comment.