@flexiui/svelte-rich-text 0.0.35 → 0.0.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,4 @@
1
1
  <script lang="ts">
2
- import { CustomTableHeader } from "./extensions/Table/CustomTableHeader";
3
- import { CustomTableCell } from "./extensions/Table/CustomTableCell";
4
- import { TableKit } from "@tiptap/extension-table";
5
- import { CellSelection } from "prosemirror-tables";
6
-
7
- import { NodeLineHeight } from "./extensions/NodeLineHeight";
8
- import { MediaGridExtension } from "./extensions/MediaGrid/MediaGrid";
9
- import { MediaGridItemExtension } from "./extensions/MediaGrid/MediaGridItem";
10
2
  import {
11
3
  Mathematics,
12
4
  migrateMathStrings,
@@ -20,15 +12,8 @@
20
12
 
21
13
  import { createEditor, Editor, EditorContent } from "svelte-tiptap";
22
14
 
23
- import StarterKit from "@tiptap/starter-kit";
24
- import Highlight from "@tiptap/extension-highlight";
25
- import TextAlign from "@tiptap/extension-text-align";
26
- import Image from "@tiptap/extension-image";
27
- import { Audio } from "./extensions/Audio";
28
- import { ListKit } from "@tiptap/extension-list";
29
- import { TextStyleKit } from "@tiptap/extension-text-style";
30
- import { EnhancedLink } from "./extensions/EnhancedLink";
31
15
  import { computePosition, offset, autoUpdate } from "@floating-ui/dom";
16
+ import { getRichTextExtensions } from "./getExtensions";
32
17
 
33
18
  declare interface Props {
34
19
  id?: string;
@@ -112,85 +97,123 @@
112
97
  ...(config ?? {}),
113
98
  });
114
99
 
115
- const extensions = [
116
- // Color.configure({ types: [TextStyle.name, ListItem.name] }),
117
- Highlight.configure({ multicolor: true }),
118
- TextStyleKit,
119
- StarterKit.configure({
120
- // Disable an included extension
121
- trailingNode: false,
122
- link: false,
123
- bulletList: false,
124
- listItem: false,
125
- orderedList: false,
126
- listKeymap: false,
127
- }),
128
- EnhancedLink,
129
- Audio.configure({
130
- HTMLAttributes: { class: "audio-player" },
131
- }),
132
- Image.configure({
133
- inline: true,
134
- }),
135
- ListKit,
136
- TextAlign.configure({
137
- types: [
138
- "heading",
139
- "paragraph",
140
- "bulletList",
141
- "taskList",
142
- "listItem",
143
- "blockquote",
144
- ],
145
- }),
146
- Mathematics.configure({
147
- inlineOptions: {
148
- onClick: (node, pos) => {
149
- // you can do anything on click, e.g. open a dialog to edit the math node
150
- // or just a prompt to edit the LaTeX code for a quick prototype
151
- const katex = prompt(
152
- "Update math LaTeX expression:",
153
- node.attrs.latex
154
- );
155
- if (katex) {
156
- $editor
157
- .chain()
158
- .setNodeSelection(pos)
159
- .updateInlineMath({ latex: katex })
160
- .focus()
161
- .run();
162
- }
100
+ // const extensions = [
101
+ // // Color.configure({ types: [TextStyle.name, ListItem.name] }),
102
+ // Highlight.configure({ multicolor: true }),
103
+ // TextStyleKit,
104
+ // StarterKit.configure({
105
+ // // Disable an included extension
106
+ // trailingNode: false,
107
+ // link: false,
108
+ // bulletList: false,
109
+ // listItem: false,
110
+ // orderedList: false,
111
+ // listKeymap: false,
112
+ // }),
113
+ // EnhancedLink,
114
+ // Audio.configure({
115
+ // HTMLAttributes: { class: "audio-player" },
116
+ // }),
117
+ // Image.configure({
118
+ // inline: true,
119
+ // }),
120
+ // ListKit,
121
+ // TextAlign.configure({
122
+ // types: [
123
+ // "heading",
124
+ // "paragraph",
125
+ // "bulletList",
126
+ // "taskList",
127
+ // "listItem",
128
+ // "blockquote",
129
+ // ],
130
+ // }),
131
+ // Mathematics.configure({
132
+ // inlineOptions: {
133
+ // onClick: (node, pos) => {
134
+ // // you can do anything on click, e.g. open a dialog to edit the math node
135
+ // // or just a prompt to edit the LaTeX code for a quick prototype
136
+ // const katex = prompt(
137
+ // "Update math LaTeX expression:",
138
+ // node.attrs.latex
139
+ // );
140
+ // if (katex) {
141
+ // $editor
142
+ // .chain()
143
+ // .setNodeSelection(pos)
144
+ // .updateInlineMath({ latex: katex })
145
+ // .focus()
146
+ // .run();
147
+ // }
148
+ // },
149
+ // },
150
+ // blockOptions: {
151
+ // // optional options for the block math node
152
+ // },
153
+ // katexOptions: {
154
+ // displayMode: false,
155
+ // throwOnError: false,
156
+ // macros: {
157
+ // "\\RR": "\\mathbb{R}",
158
+ // "\\ZZ": "\\mathbb{Z}",
159
+ // },
160
+ // },
161
+ // }),
162
+ // NodeLineHeight,
163
+ // MediaGridExtension,
164
+ // MediaGridItemExtension,
165
+ // TableKit.configure({
166
+ // table: {
167
+ // HTMLAttributes: { class: "fl-table-editable" },
168
+ // resizable: true,
169
+ // },
170
+ // }),
171
+ // CustomTableCell.configure({
172
+ // HTMLAttributes: { class: "fl-cell-editable" },
173
+ // }),
174
+ // CustomTableHeader.configure({
175
+ // HTMLAttributes: { class: "fl-cell-editable" },
176
+ // }),
177
+ // ...customExtensions,
178
+ // ];
179
+
180
+ const extensions = getRichTextExtensions({
181
+ editable: true,
182
+ customExtensions: [
183
+ ...customExtensions,
184
+ Mathematics.configure({
185
+ inlineOptions: {
186
+ onClick: (node, pos) => {
187
+ // you can do anything on click, e.g. open a dialog to edit the math node
188
+ // or just a prompt to edit the LaTeX code for a quick prototype
189
+ const katex = prompt(
190
+ "Update math LaTeX expression:",
191
+ node.attrs.latex
192
+ );
193
+ if (katex) {
194
+ $editor
195
+ .chain()
196
+ .setNodeSelection(pos)
197
+ .updateInlineMath({ latex: katex })
198
+ .focus()
199
+ .run();
200
+ }
201
+ },
163
202
  },
164
- },
165
- blockOptions: {
166
- // optional options for the block math node
167
- },
168
- katexOptions: {
169
- displayMode: false,
170
- throwOnError: false,
171
- macros: {
172
- "\\RR": "\\mathbb{R}",
173
- "\\ZZ": "\\mathbb{Z}",
203
+ blockOptions: {
204
+ // optional options for the block math node
174
205
  },
175
- },
176
- }),
177
- NodeLineHeight,
178
- MediaGridExtension,
179
- MediaGridItemExtension,
180
- TableKit.configure({
181
- table: {
182
- HTMLAttributes: { class: "fl-table-editable" },
183
- resizable: true,
184
- },
185
- }),
186
- CustomTableCell.configure({
187
- HTMLAttributes: { class: "fl-cell-editable" },
188
- }),
189
- CustomTableHeader.configure({
190
- HTMLAttributes: { class: "fl-cell-editable" },
191
- }),
192
- ...customExtensions,
193
- ];
206
+ katexOptions: {
207
+ displayMode: false,
208
+ throwOnError: false,
209
+ macros: {
210
+ "\\RR": "\\mathbb{R}",
211
+ "\\ZZ": "\\mathbb{Z}",
212
+ },
213
+ },
214
+ })
215
+ ]
216
+ });
194
217
 
195
218
  let tooltipVisible = $state(false);
196
219
  let tooltipX = $state(0);
@@ -200,6 +223,8 @@
200
223
  let currentTriggerEl: HTMLElement | null = null;
201
224
  let activeDropdownType = $state(null);
202
225
  let enterPressed = $state(false);
226
+ let fontSize = $state(16) as number;
227
+ let lineHeight = $state(null) as number;
203
228
 
204
229
  const TEXT_COLOR_PALETTE = [
205
230
  "rgb(94, 23, 235)",
@@ -517,9 +542,6 @@
517
542
  }
518
543
  }
519
544
 
520
- let fontSize = $state(16) as number;
521
- let lineHeight = $state(null) as number;
522
-
523
545
  function decrementFontSize() {
524
546
  fontSize = fontSize - 1;
525
547
  $editor
@@ -39,59 +39,81 @@ export const Audio = Node.create({
39
39
  parseHTML: el => el.hasAttribute('loop'),
40
40
  renderHTML: attrs => (attrs.loop ? { loop: true } : {}),
41
41
  },
42
- colorPlay: {
43
- default: '#333',
44
- parseHTML: el => el.getAttribute('data-color-play') || '#333',
42
+ id: {
43
+ default: `fl-audio-player-${Math.random().toString(36).substring(2, 15)}`,
44
+ parseHTML: el => el.getAttribute('data-id') || null,
45
45
  renderHTML: attrs => ({
46
- 'data-color-play': attrs.colorPlay,
46
+ 'data-id': attrs.id,
47
+ }),
48
+ },
49
+ bgColor: {
50
+ default: '#8c8c8c45',
51
+ parseHTML: el => el.getAttribute('data-bg-color'),
52
+ renderHTML: attrs => ({
53
+ 'data-bg-color': attrs.bgColor,
47
54
  }),
48
55
  },
49
- colorBar: {
50
- default: '#888',
51
- parseHTML: el => el.getAttribute('data-color-bar') || '#888',
56
+ textColor: {
57
+ default: 'currentColor',
58
+ parseHTML: el => el.getAttribute('data-text-color'),
52
59
  renderHTML: attrs => ({
53
- 'data-color-bar': attrs.colorBar,
60
+ 'data-text-color': attrs.textColor,
61
+ }),
62
+ },
63
+ borderRadius: {
64
+ default: '18px',
65
+ parseHTML: el => el.getAttribute('data-border-radius'),
66
+ renderHTML: attrs => ({
67
+ 'data-border-radius': attrs.borderRadius,
68
+ }),
69
+ },
70
+ accentColor: {
71
+ default: '#5e17eb',
72
+ parseHTML: el => el.getAttribute('data-accent-color'),
73
+ renderHTML: attrs => ({
74
+ 'data-accent-color': attrs.accentColor,
75
+ }),
76
+ },
77
+ accentColorPaused: {
78
+ default: '#fff',
79
+ parseHTML: el => el.getAttribute('data-accent-color-paused'),
80
+ renderHTML: attrs => ({
81
+ 'data-accent-color-paused': attrs.accentColorPaused,
82
+ }),
83
+ },
84
+ seekBarBgColor: {
85
+ default: '#8d8d8d3a',
86
+ parseHTML: el => el.getAttribute('data-seek-bar-bg-color'),
87
+ renderHTML: attrs => ({
88
+ 'data-seek-bar-bg-color': attrs.seekBarBgColor,
89
+ }),
90
+ },
91
+ colorPlay: {
92
+ default: '#5d5d5dc9',
93
+ parseHTML: el => el.getAttribute('data-color-play'),
94
+ renderHTML: attrs => ({
95
+ 'data-color-play': attrs.colorPlay,
54
96
  }),
55
97
  },
56
98
  maxWidth: {
57
99
  default: '100%',
58
- parseHTML: el => el.getAttribute('data-max-width') || '100%',
100
+ parseHTML: el => el.getAttribute('data-max-width'),
59
101
  renderHTML: attrs => ({
60
102
  'data-max-width': attrs.maxWidth,
61
103
  }),
62
104
  },
63
- id: {
64
- default: "fl-audio-" + Math.random().toString(36).slice(2),
65
- parseHTML: el => el.getAttribute('data-id') || null,
66
- renderHTML: attrs => ({
67
- 'data-id': attrs.id,
68
- }),
69
- }
70
105
  };
71
106
  },
72
107
  parseHTML() {
73
108
  return [
74
109
  {
75
- tag: 'audio-player',
76
- getAttrs: el => {
77
- if (!(el instanceof HTMLElement))
78
- return false;
79
- return {
80
- src: el.getAttribute('src'),
81
- controls: el.hasAttribute('controls'),
82
- autoplay: el.hasAttribute('autoplay'),
83
- loop: el.hasAttribute('loop'),
84
- colorPlay: el.getAttribute('data-color-play') || '#333',
85
- colorBar: el.getAttribute('data-color-bar') || '#888',
86
- maxWidth: el.getAttribute('data-max-width') || '100%',
87
- };
88
- },
110
+ tag: 'fl-audio-player',
89
111
  },
90
112
  ];
91
113
  },
92
114
  renderHTML({ HTMLAttributes }) {
93
115
  return [
94
- 'audio-player',
116
+ 'fl-audio-player',
95
117
  mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),
96
118
  ];
97
119
  },
@@ -7,17 +7,27 @@
7
7
  import WaveSurfer from "wavesurfer.js";
8
8
  import { activeAudioId } from "./audioStore";
9
9
 
10
- export let id: string = "audio-" + Math.random().toString(36).slice(2);
10
+ export let id: string;
11
11
  export let src: string;
12
+ export let controls: any
12
13
  export let showSeekbar: boolean = true;
13
14
  export let config: any = {};
14
-
15
15
  export let playerType: "waveform" | "seekbar" = "waveform";
16
+ export let bgColor: string;
17
+ export let textColor: string;
18
+ export let borderRadius: string;
19
+ export let accentColor: string;
20
+ export let accentColorPaused: string;
21
+ export let colorPlay: string;
22
+ export let maxWidth: string;
16
23
 
17
24
  let wavesurfer: WaveSurfer | null = null;
25
+ let waveformEl: HTMLDivElement | null = null;
18
26
  let wavesurferReady: boolean = false;
19
27
  let loading: boolean = true;
20
- let audio: any = null;
28
+ // let audio: any = null;
29
+ let audio: HTMLAudioElement | null = null;
30
+
21
31
  let playing: boolean = false;
22
32
  let mounted: boolean = false;
23
33
  let seekbarEl: HTMLDivElement | null = null;
@@ -30,6 +40,8 @@
30
40
  let audioDuration: number = 0;
31
41
  let audioCurrentTime: number = 0;
32
42
 
43
+ id = id + "-" + Math.random().toString(36).substring(2, 15);
44
+
33
45
  function formatTime(seconds: number) {
34
46
  if (isNaN(seconds) || seconds < 0) return "0:00";
35
47
 
@@ -105,8 +117,12 @@
105
117
  if (WaveSurfer) {
106
118
 
107
119
  setTimeout(() => {
120
+ const identifier = "waveform-" + id;
121
+ console.log({ identifier });
122
+ console.log({ waveformEl });
123
+
108
124
  wavesurfer = WaveSurfer?.create({
109
- container: "#waveform-" + id,
125
+ container: waveformEl,
110
126
  height: 46,
111
127
  normalize: false,
112
128
  waveColor: "#b0b0b0",
@@ -147,10 +163,10 @@
147
163
  // wavesurfer?.stop();
148
164
  // });
149
165
 
150
- audio = new Audio(src);
166
+ // audio = new Audio(src);
167
+ // audio.load();
151
168
  audio.volume = volume;
152
169
  audio.preload = "auto";
153
- audio.load();
154
170
 
155
171
  audio.addEventListener("loadedmetadata", () => {
156
172
  audioDuration = audio.duration;
@@ -168,6 +184,19 @@
168
184
  }
169
185
  });
170
186
 
187
+ audio.onended = () => {
188
+ playing = false;
189
+ console.log("Audio playback ended");
190
+ };
191
+
192
+ audio.addEventListener("play", () => {
193
+ playing = true;
194
+ });
195
+
196
+ audio.addEventListener("pause", () => {
197
+ playing = false;
198
+ });
199
+
171
200
  setTimeout(() => {
172
201
  loading = false;
173
202
  }, 500);
@@ -257,7 +286,19 @@
257
286
  }
258
287
  </script>
259
288
 
260
- <div class="audio-player" {id} class:playing>
289
+ <div
290
+ class="audio-player"
291
+ {id}
292
+ class:playing
293
+ style={`
294
+ --player-bg-color: ${bgColor};
295
+ --player-play-btn-bg: ${colorPlay};
296
+ --player-primary-color: ${accentColor};
297
+ --player-progress-default-bg: ${accentColorPaused};
298
+ --player-text-color: ${textColor};
299
+ --player-border-radius: ${borderRadius};
300
+ `}
301
+ >
261
302
  <button
262
303
  onclick={() => togglePlayPause()}
263
304
  type="button"
@@ -296,6 +337,7 @@
296
337
  <!-- <span class="media-item-number">{index+1}</span> -->
297
338
 
298
339
  <div
340
+ bind:this={waveformEl}
299
341
  class="audio-player-wave"
300
342
  id={"waveform-" + id}
301
343
  class:hidden={mounted && !wavesurferReady}
@@ -435,11 +477,12 @@
435
477
  </div>
436
478
  </div>
437
479
 
438
- <!-- {#if mounted && !wavesurferReady}
439
- <div class="audio-player-time">
440
- 0:51
441
- </div>
442
- {/if} -->
480
+ <!-- Reproductor de audo nativo -->
481
+ <audio
482
+ bind:this={audio}
483
+ src={src}
484
+ id={'native-audio-' + id}
485
+ ></audio>
443
486
  </div>
444
487
 
445
488
  <style>
@@ -450,13 +493,14 @@
450
493
 
451
494
  .audio-player {
452
495
  --player-primary-color: #5e17eb;
453
- --player-bg-color: #455f7414;
496
+ --player-bg-color: #8c8c8c45;
454
497
  --player-border-radius: 18px;
455
498
  --player-seekbar-bg: #8d8d8d3a;
456
499
  --player-seekbar-height: 6px;
457
500
  --player-progress-default-bg: #f5f5f5;
458
501
  --player-play-btn-bg: #8d8d8d26;
459
502
  --player-play-btn-color: #fff;
503
+ --player-text-color: currentColor;
460
504
 
461
505
  display: flex;
462
506
  align-items: center;
@@ -466,6 +510,7 @@
466
510
  padding: 12px;
467
511
  width: 100%;
468
512
  box-sizing: border-box;
513
+ color: var(--player-text-color);
469
514
 
470
515
  &.playing {
471
516
  .audio-player-wave {
@@ -490,6 +535,16 @@
490
535
  border-radius: 100%;
491
536
  outline-offset: 4px;
492
537
  outline-color: var(--player-play-btn-bg);
538
+ cursor: pointer;
539
+ transition: filter 0.3s ease, transform 0.3s ease, background 0.3s ease;
540
+
541
+ &:hover {
542
+ /* background: var(--player-primary-color); */
543
+ &:not(.playing) {
544
+ filter: brightness(1.2);
545
+ }
546
+ transform: scale(1.06);
547
+ }
493
548
 
494
549
  svg {
495
550
  width: 20px;
@@ -581,7 +636,7 @@
581
636
  margin-right: 4px;
582
637
 
583
638
  &:hover {
584
- background: #0d121612;
639
+ background: #7a7a7a17;
585
640
  }
586
641
 
587
642
  &:hover .audio-player-seekbar,
@@ -615,6 +670,7 @@
615
670
  border: none;
616
671
  padding: 4px;
617
672
  background: #0d121600;
673
+ color: currentColor;
618
674
  border-radius: 100%;
619
675
  height: 36px;
620
676
  width: 36px;
@@ -1,11 +1,19 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
2
  declare const __propDef: {
3
3
  props: {
4
- id?: string;
4
+ id: string;
5
5
  src: string;
6
+ controls: any;
6
7
  showSeekbar?: boolean;
7
8
  config?: any;
8
9
  playerType?: "waveform" | "seekbar";
10
+ bgColor: string;
11
+ textColor: string;
12
+ borderRadius: string;
13
+ accentColor: string;
14
+ accentColorPaused: string;
15
+ colorPlay: string;
16
+ maxWidth: string;
9
17
  };
10
18
  events: {
11
19
  [evt: string]: CustomEvent<any>;
@@ -62,12 +62,8 @@
62
62
  <NodeViewWrapper class="fl-audio-player-wrapper">
63
63
  <div
64
64
  bind:this={targetElement}
65
- class="fl-audio-player"
65
+ class="fl-audio-player-container"
66
66
  class:selected={selected}
67
- style="
68
- --color-play: {attrs.colorPlay};
69
- --color-bar: {attrs.colorBar};
70
- "
71
67
  >
72
68
  <!-- <audio
73
69
  src={attrs.src}
@@ -76,7 +72,18 @@
76
72
  loop={attrs.loop}
77
73
  ></audio> -->
78
74
 
79
- <AudioPlayer src={attrs.src}></AudioPlayer>
75
+ <AudioPlayer
76
+ id={attrs.id}
77
+ controls={true}
78
+ src={attrs.src}
79
+ bgColor={attrs.bgColor}
80
+ textColor={attrs.textColor}
81
+ borderRadius={attrs.borderRadius}
82
+ accentColor={attrs.accentColor}
83
+ accentColorPaused={attrs.accentColorPaused}
84
+ colorPlay={attrs.colorPlay}
85
+ maxWidth={attrs.maxWidth}
86
+ ></AudioPlayer>
80
87
 
81
88
  {#if selected}
82
89
  <span
@@ -93,7 +100,7 @@
93
100
  </NodeViewWrapper>
94
101
 
95
102
  <style>
96
- .fl-audio-player {
103
+ .fl-audio-player-container {
97
104
  display: flex;
98
105
  align-items: center;
99
106
  position: relative;
@@ -0,0 +1,4 @@
1
+ export declare function getRichTextExtensions(options?: {
2
+ editable?: boolean;
3
+ customExtensions?: any[];
4
+ }): any[];
@@ -0,0 +1,66 @@
1
+ // getExtensions.ts
2
+ import StarterKit from "@tiptap/starter-kit";
3
+ import Highlight from "@tiptap/extension-highlight";
4
+ import TextAlign from "@tiptap/extension-text-align";
5
+ import Image from "@tiptap/extension-image";
6
+ import { ListKit } from "@tiptap/extension-list";
7
+ import { TextStyleKit } from "@tiptap/extension-text-style";
8
+ import { Mathematics } from "@tiptap/extension-mathematics";
9
+ import { TableKit } from "@tiptap/extension-table";
10
+ import { Audio } from "./extensions/Audio";
11
+ import { NodeLineHeight } from "./extensions/NodeLineHeight";
12
+ import { MediaGridExtension } from "./extensions/MediaGrid/MediaGrid";
13
+ import { MediaGridItemExtension } from "./extensions/MediaGrid/MediaGridItem";
14
+ import { CustomTableCell } from "./extensions/Table/CustomTableCell";
15
+ import { CustomTableHeader } from "./extensions/Table/CustomTableHeader";
16
+ import { EnhancedLink } from "./extensions/EnhancedLink";
17
+ export function getRichTextExtensions(options) {
18
+ const { editable = false, customExtensions = [] } = options ?? {};
19
+ return [
20
+ Highlight.configure({ multicolor: true }),
21
+ TextStyleKit,
22
+ StarterKit.configure({
23
+ trailingNode: false,
24
+ link: false,
25
+ bulletList: false,
26
+ listItem: false,
27
+ orderedList: false,
28
+ listKeymap: false,
29
+ }),
30
+ EnhancedLink,
31
+ Image.configure({ inline: true }),
32
+ Audio.configure({
33
+ HTMLAttributes: { class: "audio-player" },
34
+ }),
35
+ ListKit,
36
+ TextAlign.configure({
37
+ types: [
38
+ "heading",
39
+ "paragraph",
40
+ "bulletList",
41
+ "taskList",
42
+ "listItem",
43
+ "blockquote",
44
+ ],
45
+ }),
46
+ NodeLineHeight,
47
+ MediaGridExtension,
48
+ MediaGridItemExtension,
49
+ TableKit.configure({
50
+ table: {
51
+ HTMLAttributes: { class: "fl-table-editable" },
52
+ resizable: true,
53
+ },
54
+ tableCell: false,
55
+ tableHeader: false,
56
+ }),
57
+ CustomTableCell.configure({
58
+ HTMLAttributes: { class: "fl-cell-editable" },
59
+ }),
60
+ CustomTableHeader.configure({
61
+ HTMLAttributes: { class: "fl-cell-editable" },
62
+ }),
63
+ !editable ? Mathematics : null,
64
+ ...customExtensions,
65
+ ];
66
+ }
package/dist/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  import RichText from './RichText.svelte';
2
- export { RichText };
2
+ import { renderHTMLFromJSON } from './renderRichText';
3
+ export { RichText, renderHTMLFromJSON };
package/dist/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  import RichText from './RichText.svelte';
2
- export { RichText };
2
+ import { renderHTMLFromJSON } from './renderRichText';
3
+ export { RichText, renderHTMLFromJSON };
@@ -0,0 +1,7 @@
1
+ interface RenderOptions {
2
+ json: any;
3
+ customExtensions?: any[];
4
+ customNodeMapping?: any;
5
+ }
6
+ export declare function renderHTMLFromJSON({ json, customExtensions, customNodeMapping }: RenderOptions): string;
7
+ export {};
@@ -0,0 +1,65 @@
1
+ import { renderToHTMLString, serializeChildrenToHTMLString } from "@tiptap/static-renderer";
2
+ import katex from "katex";
3
+ import { getRichTextExtensions } from "./getExtensions";
4
+ const nodeMapping = {
5
+ inlineMath({ node }) {
6
+ const latex = node.attrs.latex || '';
7
+ return `<span class="math-inline">${katex.renderToString(latex, { throwOnError: false })}</span>`;
8
+ },
9
+ MediaGridComponent({ node, children }) {
10
+ const cols = node.attrs.cols || 2;
11
+ const gap = node.attrs.gap || '1rem';
12
+ const showIndicator = node.attrs.showIndicator || false;
13
+ const indicatorType = node.attrs.indicatorType || 'numeric';
14
+ return `
15
+ <div
16
+ class="fl-media-grid"
17
+ data-cols="${cols}"
18
+ data-gap="${gap}"
19
+ data-show-indicator="${showIndicator}"
20
+ data-indicator-type="${indicatorType}"
21
+ style="
22
+ --fl-grid-cols: ${cols};
23
+ --fl-grid-gap: ${gap};
24
+ ">
25
+ ${serializeChildrenToHTMLString(children)}
26
+ </div>`;
27
+ },
28
+ gridItem({ node, children }) {
29
+ return `<div class="fl-grid-item">${serializeChildrenToHTMLString(children)}</div>`;
30
+ },
31
+ audio({ node, children }) {
32
+ const { id, src, controls, bgColor, textColor, borderRadius, accentColor, accentColorPaused, maxWidth, colorPlay } = node.attrs;
33
+ return `
34
+ <fl-audio-player
35
+ class="fl-audio-player"
36
+ id="${id}"
37
+ src="${src}"
38
+ controls="${controls}"
39
+ bgColor="${bgColor}"
40
+ textColor="${textColor}"
41
+ borderRadius="${borderRadius}"
42
+ accentColor="${accentColor}"
43
+ accentColorPaused="${accentColorPaused}"
44
+ maxWidth="${maxWidth}"
45
+ colorPlay="${colorPlay}"
46
+ >
47
+ </fl-audio-player>
48
+ `;
49
+ },
50
+ };
51
+ export function renderHTMLFromJSON({ json, customExtensions = [], customNodeMapping = {} }) {
52
+ const extensions = getRichTextExtensions({ customExtensions });
53
+ const finalNodeMapping = {
54
+ ...nodeMapping,
55
+ ...customNodeMapping,
56
+ };
57
+ const html = renderToHTMLString({
58
+ extensions: extensions, // using your extensions
59
+ content: json,
60
+ options: {
61
+ nodeMapping: finalNodeMapping,
62
+ }
63
+ });
64
+ return html;
65
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flexiui/svelte-rich-text",
3
- "version": "0.0.35",
3
+ "version": "0.0.37",
4
4
  "description": "A lightweight and flexible rich text editor component for Svelte",
5
5
  "keywords": [
6
6
  "svelte",