Skip to content

Commit 0aec531

Browse files
committed
Add rich text editor supports for comment widget
Signed-off-by: Ryan Wang <i@ryanc.cc>
1 parent b4a419d commit 0aec531

9 files changed

Lines changed: 2812 additions & 319 deletions

File tree

package.json

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,17 @@
3030
"husky": "^9.1.7",
3131
"lint-staged": "^16.1.2",
3232
"typescript": "~5.3.3",
33-
"vite": "^5.1.4"
33+
"vite": "^7.0.6",
34+
"vite-plugin-dts": "^4.5.4"
3435
},
35-
"packageManager": "pnpm@10.10.0+sha512.d615db246fe70f25dcfea6d8d73dee782ce23e2245e3c4f6f888249fb568149318637dca73c2c5c8ef2a4ca0d5657fb9567188bfab47f566d1ee6ce987815c39"
36+
"packageManager": "pnpm@10.10.0+sha512.d615db246fe70f25dcfea6d8d73dee782ce23e2245e3c4f6f888249fb568149318637dca73c2c5c8ef2a4ca0d5657fb9567188bfab47f566d1ee6ce987815c39",
37+
"pnpm": {
38+
"overrides": {
39+
"vite": "npm:rolldown-vite@7.0.10"
40+
}
41+
},
42+
"dependencies": {
43+
"@tiptap/extensions": "^3.0.9",
44+
"github-markdown-css": "^5.8.1"
45+
}
3646
}

packages/comment-widget/package.json

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,24 +27,29 @@
2727
"var.css"
2828
],
2929
"scripts": {
30-
"build": "tsc",
31-
"dev": "tsc -w",
32-
"locale:extract": "lit-localize extract",
33-
"locale:build": "lit-localize build"
30+
"build": "vite build",
31+
"dev": "vite build --watch",
32+
"locale:build": "lit-localize build",
33+
"locale:extract": "lit-localize extract"
3434
},
3535
"dependencies": {
3636
"@emoji-mart/data": "^1.2.1",
3737
"@halo-dev/api-client": "^2.21.1",
3838
"@lit/context": "^1.1.6",
3939
"@lit/localize": "^0.12.2",
40+
"@tiptap/core": "^3.0.9",
41+
"@tiptap/pm": "^3.0.9",
42+
"@tiptap/starter-kit": "^3.0.9",
4043
"dayjs": "^1.11.13",
4144
"emoji-mart": "^5.6.0",
4245
"es-toolkit": "^1.39.8",
4346
"javascript-time-ago": "^2.5.11",
4447
"lit": "^3.3.1"
4548
},
4649
"devDependencies": {
50+
"@iconify/json": "^2.2.367",
4751
"@lit/localize-tools": "^0.8.0",
48-
"lit-analyzer": "^2.0.3"
52+
"lit-analyzer": "^2.0.3",
53+
"unocss": "^66.4.1"
4954
}
5055
}

packages/comment-widget/src/base-comment-item.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import './user-avatar';
22
import { msg } from '@lit/localize';
3-
import { css, html, LitElement } from 'lit';
3+
import contentStyles from 'github-markdown-css/github-markdown-light.css?inline';
4+
import { css, html, LitElement, unsafeCSS } from 'lit';
45
import { property } from 'lit/decorators.js';
6+
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
57
import baseStyles from './styles/base';
68
import varStyles from './styles/var';
79
import { formatDate, timeAgo } from './utils/date';
@@ -40,19 +42,27 @@ export class BaseCommentItem extends LitElement {
4042
<div class="item__meta">
4143
${
4244
this.userWebsite
43-
? html`<a class="item__author" target="_blank" href=${this.userWebsite}>
45+
? html`<a
46+
class="item__author"
47+
target="_blank"
48+
href=${this.userWebsite}
49+
>
4450
${this.userDisplayName}
4551
</a>`
4652
: html`<div class="item__author">${this.userDisplayName}</div>`
4753
}
4854
<div class="item__meta-info" title=${formatDate(this.creationTime)}>
4955
${timeAgo(this.creationTime)}
5056
</div>
51-
${!this.approved ? html`<div class="item__meta-info">${msg('Reviewing')}</div>` : ''}
57+
${
58+
!this.approved
59+
? html`<div class="item__meta-info">${msg('Reviewing')}</div>`
60+
: ''
61+
}
5262
</div>
5363
54-
<div class="item__content">
55-
<pre><slot name="pre-content"></slot>${this.content}</pre>
64+
<div class="item__content markdown-body">
65+
<div><slot name="pre-content"></slot>${unsafeHTML(this.content)}</div>
5666
</div>
5767
5868
<div class="item__actions">
@@ -67,6 +77,7 @@ export class BaseCommentItem extends LitElement {
6777
static override styles = [
6878
varStyles,
6979
baseStyles,
80+
unsafeCSS(contentStyles),
7081
css`
7182
.item {
7283
display: flex;

packages/comment-widget/src/base-form.ts

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@ import {
1414
nameContext,
1515
toastContext,
1616
} from './context';
17-
import './emoji-button';
1817
import './icons/icon-loading';
1918
import { msg } from '@lit/localize';
2019
import type { ToastManager } from './lit-toast';
2120
import baseStyles from './styles/base';
2221
import varStyles from './styles/var';
2322
import type { ConfigMapData } from './types';
23+
import './comment-editor';
24+
import type { CommentEditor } from './comment-editor';
2425

2526
export class BaseForm extends LitElement {
2627
@consume({ context: baseUrlContext })
@@ -64,6 +65,8 @@ export class BaseForm extends LitElement {
6465

6566
textareaRef: Ref<HTMLTextAreaElement> = createRef<HTMLTextAreaElement>();
6667

68+
editorRef: Ref<CommentEditor> = createRef<CommentEditor>();
69+
6770
get customAccount() {
6871
return JSON.parse(
6972
localStorage.getItem('halo-comment-custom-account') || '{}'
@@ -168,14 +171,6 @@ export class BaseForm extends LitElement {
168171
target.style.height = `${target.scrollHeight}px`;
169172
}
170173

171-
onEmojiSelect(e: CustomEvent) {
172-
const data = e.detail;
173-
if (this.textareaRef.value) {
174-
this.textareaRef.value.value += data.native;
175-
this.textareaRef.value.focus();
176-
}
177-
}
178-
179174
onKeydown(e: KeyboardEvent) {
180175
if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {
181176
const form = this.shadowRoot?.querySelector('form');
@@ -197,15 +192,7 @@ export class BaseForm extends LitElement {
197192
override render() {
198193
return html`
199194
<form class="form" @submit="${this.onSubmit}">
200-
<textarea
201-
class="form__editor"
202-
${ref(this.textareaRef)}
203-
placeholder=${msg('Write a comment')}
204-
rows="4"
205-
name="content"
206-
required
207-
@input=${this.onContentInput}
208-
></textarea>
195+
<comment-editor ${ref(this.editorRef)}></comment-editor>
209196
210197
${
211198
!this.currentUser && this.allowAnonymousComments
@@ -269,7 +256,6 @@ export class BaseForm extends LitElement {
269256
: ''
270257
}
271258
272-
<emoji-button @emoji-select=${this.onEmojiSelect}></emoji-button>
273259
<button
274260
.disabled=${this.submitting}
275261
type="submit"
@@ -299,8 +285,13 @@ export class BaseForm extends LitElement {
299285
}
300286

301287
private debouncedSubmit = debounce((data: Record<string, unknown>) => {
288+
const content = this.editorRef.value?.editor?.getHTML() || '';
289+
302290
const event = new CustomEvent('submit', {
303-
detail: data,
291+
detail: {
292+
...data,
293+
content,
294+
},
304295
});
305296
this.dispatchEvent(event);
306297
}, 300);
@@ -327,10 +318,12 @@ export class BaseForm extends LitElement {
327318
resetForm() {
328319
const form = this.shadowRoot?.querySelector('form');
329320
form?.reset();
321+
this.editorRef.value?.reset();
330322
}
331323

332324
setFocus() {
333325
this.textareaRef.value?.focus();
326+
this.editorRef.value?.setFocus();
334327
}
335328

336329
static override styles = [

0 commit comments

Comments
 (0)