@seorii/tiptap 0.1.2 → 0.2.1

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.
@@ -0,0 +1,20 @@
1
+ import { PluginKey } from "prosemirror-state";
2
+ import type { Editor } from "@tiptap/core";
3
+ export declare const emoji: {
4
+ pluginKey: PluginKey<any>;
5
+ char: string;
6
+ items: ({ query }: {
7
+ query: any;
8
+ }) => {
9
+ title: string;
10
+ command: {};
11
+ }[];
12
+ render: () => {
13
+ onStart: (props: any) => void;
14
+ onUpdate(props: any): void;
15
+ onKeyDown(props: any): true | undefined;
16
+ onExit(): void;
17
+ };
18
+ };
19
+ declare const _default: (editor: Editor) => import("prosemirror-state").Plugin<any>;
20
+ export default _default;
@@ -0,0 +1,81 @@
1
+ import { slashVisible, slashItems, slashLocaltion, slashProps, slashDetail } from './stores';
2
+ import { PluginKey } from "prosemirror-state";
3
+ import Suggestion from "@tiptap/suggestion";
4
+ //@ts-ignore
5
+ import emojis from 'emojis-list';
6
+ //@ts-ignore
7
+ import tags from 'emojis-keywords';
8
+ const max = 10;
9
+ function fixRange(editor, range, split = '/') {
10
+ const { state } = editor.view, { selection, doc } = state;
11
+ if (selection.$to.nodeBefore?.text?.includes?.(split)) {
12
+ range.from = range.to;
13
+ while (range.from > 0 && doc.textBetween(range.from - 1, range.from) !== split) {
14
+ try {
15
+ range.from -= 1;
16
+ }
17
+ catch (e) {
18
+ range.from += 2;
19
+ break;
20
+ }
21
+ }
22
+ range.from -= 1;
23
+ }
24
+ while (range.to < selection.to && doc.textBetween(range.to, range.to + 1) !== ' ') {
25
+ try {
26
+ range.to += 1;
27
+ }
28
+ catch (e) {
29
+ range.to -= 1;
30
+ break;
31
+ }
32
+ }
33
+ return range;
34
+ }
35
+ export const emoji = {
36
+ pluginKey: new PluginKey('slash-emoji'),
37
+ char: ':',
38
+ items: ({ query }) => {
39
+ query = ':' + query.toLowerCase();
40
+ const filtered = [];
41
+ for (let i = 0; i < emojis.length; i++) {
42
+ if (tags[i]?.includes?.(query))
43
+ filtered.push({
44
+ title: emojis[i] + ' ' + tags[i],
45
+ command: ({ editor, range }) => {
46
+ editor.chain().deleteRange(fixRange(editor, range, ':')).insertContent(emojis[i] + ' ').run();
47
+ }
48
+ });
49
+ if (filtered.length >= max)
50
+ break;
51
+ }
52
+ return filtered;
53
+ },
54
+ render: () => {
55
+ return {
56
+ onStart: (props) => {
57
+ let editor = props.editor;
58
+ let range = props.range;
59
+ let location = props.clientRect();
60
+ slashProps.set({ editor, range });
61
+ slashVisible.set(true);
62
+ slashLocaltion.set({ x: location.x, y: location.y, height: location.height });
63
+ slashItems.set(props.items);
64
+ slashDetail.set('emoji');
65
+ },
66
+ onUpdate(props) {
67
+ slashItems.set(props.items);
68
+ },
69
+ onKeyDown(props) {
70
+ if (props.event.key === 'Escape') {
71
+ slashVisible.set(false);
72
+ return true;
73
+ }
74
+ },
75
+ onExit() {
76
+ slashVisible.set(false);
77
+ }
78
+ };
79
+ }
80
+ };
81
+ export default (editor) => Suggestion({ ...emoji, editor });
@@ -11,3 +11,4 @@ export declare const slashProps: import("svelte/store").Writable<{
11
11
  range: null;
12
12
  }>;
13
13
  export declare const slashDetail: import("svelte/store").Writable<null>;
14
+ export declare const slashSelection: import("svelte/store").Writable<null>;
@@ -4,3 +4,4 @@ export const slashItems = writable([]);
4
4
  export const slashLocaltion = writable({ x: 0, y: 0, height: 0 });
5
5
  export const slashProps = writable({ editor: null, range: null });
6
6
  export const slashDetail = writable(null);
7
+ export const slashSelection = writable(null);
@@ -1,17 +1,13 @@
1
- declare const _default: {
1
+ import { PluginKey } from "prosemirror-state";
2
+ import { Editor } from "@tiptap/core";
3
+ export declare const suggest: {
4
+ pluginKey: PluginKey<any>;
5
+ char: string;
2
6
  items: ({ query }: {
3
7
  query: any;
4
8
  }) => {
5
9
  section: any;
6
- list: {
7
- icon: string;
8
- title: any;
9
- subtitle: any;
10
- command: ({ editor, range }: {
11
- editor: any;
12
- range: any;
13
- }) => void;
14
- }[];
10
+ list: any[];
15
11
  }[];
16
12
  render: () => {
17
13
  onStart: (props: any) => void;
@@ -20,4 +16,5 @@ declare const _default: {
20
16
  onExit(): void;
21
17
  };
22
18
  };
19
+ declare const _default: (editor: Editor) => import("prosemirror-state").Plugin<any>;
23
20
  export default _default;
@@ -1,7 +1,38 @@
1
- import { slashVisible, slashItems, slashLocaltion, slashProps, slashDetail } from './stores';
1
+ import { slashVisible, slashItems, slashLocaltion, slashProps, slashDetail, slashSelection } from './stores';
2
2
  import i18n from "../../i18n";
3
3
  import { fallbackUpload } from "../image/dragdrop";
4
- export default {
4
+ import { PluginKey } from "prosemirror-state";
5
+ import { Editor } from "@tiptap/core";
6
+ import Suggestion from "@tiptap/suggestion";
7
+ function fixRange(editor, range, split = '/') {
8
+ const { state } = editor.view, { selection, doc } = state;
9
+ if (selection.$to.nodeBefore?.text?.includes?.(split)) {
10
+ range.from = range.to;
11
+ while (range.from > 0 && doc.textBetween(range.from - 1, range.from) !== split) {
12
+ try {
13
+ range.from -= 1;
14
+ }
15
+ catch (e) {
16
+ range.from += 2;
17
+ break;
18
+ }
19
+ }
20
+ range.from -= 1;
21
+ }
22
+ while (range.to < selection.to && doc.textBetween(range.to, range.to + 1) !== ' ') {
23
+ try {
24
+ range.to += 1;
25
+ }
26
+ catch (e) {
27
+ range.to -= 1;
28
+ break;
29
+ }
30
+ }
31
+ return range;
32
+ }
33
+ export const suggest = {
34
+ pluginKey: new PluginKey('slash-suggest'),
35
+ char: '/',
5
36
  items: ({ query }) => {
6
37
  const raw = [
7
38
  {
@@ -11,7 +42,7 @@ export default {
11
42
  title: i18n('title') + ' 1',
12
43
  subtitle: i18n('title1Info'),
13
44
  command: ({ editor, range }) => {
14
- editor.chain().focus().deleteRange(range).setNode('heading', { level: 1 }).run();
45
+ editor.chain().focus().deleteRange(fixRange(editor, range)).setNode('heading', { level: 1 }).run();
15
46
  }
16
47
  },
17
48
  {
@@ -19,7 +50,7 @@ export default {
19
50
  title: i18n('title') + ' 2',
20
51
  subtitle: i18n('title2Info'),
21
52
  command: ({ editor, range }) => {
22
- editor.chain().focus().deleteRange(range).setNode('heading', { level: 2 }).run();
53
+ editor.chain().focus().deleteRange(fixRange(editor, range)).setNode('heading', { level: 2 }).run();
23
54
  }
24
55
  },
25
56
  {
@@ -27,7 +58,7 @@ export default {
27
58
  title: i18n('title') + ' 3',
28
59
  subtitle: i18n('title3Info'),
29
60
  command: ({ editor, range }) => {
30
- editor.chain().focus().deleteRange(range).setNode('heading', { level: 3 }).run();
61
+ editor.chain().focus().deleteRange(fixRange(editor, range)).setNode('heading', { level: 3 }).run();
31
62
  }
32
63
  },
33
64
  {
@@ -35,7 +66,7 @@ export default {
35
66
  title: i18n('unorderedList'),
36
67
  subtitle: i18n('unorderedListInfo'),
37
68
  command: ({ editor, range }) => {
38
- editor.commands.deleteRange(range);
69
+ editor.commands.deleteRange(fixRange(editor, range));
39
70
  editor.commands.toggleBulletList();
40
71
  }
41
72
  },
@@ -44,7 +75,7 @@ export default {
44
75
  title: i18n('numberList'),
45
76
  subtitle: i18n('numberListInfo'),
46
77
  command: ({ editor, range }) => {
47
- editor.commands.deleteRange(range);
78
+ editor.commands.deleteRange(fixRange(editor, range));
48
79
  editor.commands.toggleOrderedList();
49
80
  }
50
81
  }
@@ -52,11 +83,13 @@ export default {
52
83
  },
53
84
  {
54
85
  section: i18n('block'), list: [
86
+ ...(window.__tiptap_blocks),
55
87
  {
56
88
  icon: 'image',
57
89
  title: i18n('image'),
58
90
  subtitle: i18n('imageInfo'),
59
91
  command: ({ editor, range }) => {
92
+ editor.chain().focus().deleteRange(fixRange(editor, range)).run();
60
93
  const input = document.createElement('input');
61
94
  input.type = 'file';
62
95
  input.accept = 'image/*';
@@ -78,7 +111,7 @@ export default {
78
111
  title: i18n('codeBlock'),
79
112
  subtitle: i18n('codeBlockInfo'),
80
113
  command: ({ editor, range }) => {
81
- editor.chain().focus().deleteRange(range).setNode('codeBlock').run();
114
+ editor.chain().focus().deleteRange(fixRange(editor, range)).setNode('codeBlock').run();
82
115
  }
83
116
  },
84
117
  {
@@ -87,7 +120,7 @@ export default {
87
120
  subtitle: i18n('mathBlockInfo'),
88
121
  command: ({ editor, range }) => {
89
122
  const { to } = range;
90
- editor.chain().focus().deleteRange(range).setNode('math_display').focus().run();
123
+ editor.chain().focus().deleteRange(fixRange(editor, range)).setNode('math_display').focus().run();
91
124
  }
92
125
  },
93
126
  {
@@ -95,7 +128,7 @@ export default {
95
128
  title: i18n('table'),
96
129
  subtitle: i18n('tableInfo'),
97
130
  command: ({ editor, range }) => {
98
- editor.chain().focus().insertTable({ rows: 2, cols: 3 }).run();
131
+ editor.chain().focus().deleteRange(fixRange(editor, range)).insertTable({ rows: 2, cols: 3 }).run();
99
132
  }
100
133
  },
101
134
  {
@@ -103,7 +136,7 @@ export default {
103
136
  title: i18n('blockquote'),
104
137
  subtitle: i18n('blockquoteInfo'),
105
138
  command: ({ editor, range }) => {
106
- editor.chain().focus().deleteRange(range).setBlockquote().focus().run();
139
+ editor.chain().focus().deleteRange(fixRange(editor, range)).setBlockquote().focus().run();
107
140
  }
108
141
  },
109
142
  {
@@ -111,6 +144,7 @@ export default {
111
144
  title: i18n('iframe'),
112
145
  subtitle: i18n('iframeInfo'),
113
146
  command: ({ editor, range }) => {
147
+ slashSelection.set(() => editor.chain().focus().deleteRange(fixRange(editor, range)).run());
114
148
  slashDetail.set('iframe');
115
149
  }
116
150
  },
@@ -119,6 +153,7 @@ export default {
119
153
  title: i18n('youtube'),
120
154
  subtitle: i18n('youtubeInfo'),
121
155
  command: ({ editor, range }) => {
156
+ slashSelection.set(() => editor.chain().focus().deleteRange(fixRange(editor, range)).run());
122
157
  slashDetail.set('youtube');
123
158
  }
124
159
  }
@@ -158,3 +193,4 @@ export default {
158
193
  };
159
194
  }
160
195
  };
196
+ export default (editor) => Suggestion({ ...suggest, editor });
@@ -63,7 +63,7 @@ $grip-margin: 3px;
63
63
  }
64
64
  }
65
65
 
66
- .editor & {
66
+ .editable & {
67
67
  .grip-column, .grip-row, .grip-table {
68
68
  opacity: 1;
69
69
  cursor: pointer;
@@ -9,7 +9,7 @@
9
9
  background-color: var(--primary-light6);
10
10
  opacity: 0;
11
11
 
12
- .editor & {
12
+ .editable & {
13
13
  opacity: 1;
14
14
  }
15
15
  }
@@ -17,7 +17,7 @@
17
17
  &.resize-cursor {
18
18
  pointer-events: none;
19
19
 
20
- .editor & {
20
+ .editable & {
21
21
  pointer-events: initial;
22
22
  cursor: ew-resize;
23
23
  cursor: col-resize; /* stylelint-disable declaration-block-no-duplicate-properties */
@@ -69,7 +69,7 @@
69
69
  }
70
70
  }
71
71
 
72
- .editor {
72
+ .editable {
73
73
  .ProseMirror {
74
74
  .tableWrapper {
75
75
  padding: 10px;
@@ -1,5 +1,4 @@
1
1
  @import './style/grip';
2
2
  @import './style/table';
3
- @import './style/theme';
4
3
  @import './style/cell';
5
4
  @import './style/resize';
@@ -1,16 +1,17 @@
1
- <script>import { Button, IconButton, Input, List, TwoLine } from "nunui";
1
+ <script>import { Button, IconButton, Input, List, OneLine, TwoLine } from "nunui";
2
2
  import { getContext } from "svelte";
3
- import { slashVisible, slashItems, slashLocaltion, slashProps, slashDetail } from '../plugin/command/stores';
3
+ import { slashVisible, slashItems, slashLocaltion, slashProps, slashDetail, slashSelection } from '../plugin/command/stores';
4
4
  import { fly, slide } from "svelte/transition";
5
5
  import { quartOut } from "svelte/easing";
6
6
  import i18n from "../i18n";
7
7
  const tiptap = getContext('editor');
8
8
  export let selectedIndex = 0;
9
9
  let height = 0, elements = [];
10
- let iframe = '';
10
+ let iframe = '', focus;
11
11
  $: if ($slashVisible) {
12
12
  iframe = '';
13
13
  }
14
+ $: setTimeout(() => focus?.focus?.(), 100);
14
15
  </script>
15
16
 
16
17
  <svelte:window bind:innerHeight={height}/>
@@ -26,16 +27,19 @@ $: if ($slashVisible) {
26
27
  <IconButton icon="arrow_back" on:click={() => $slashDetail = ''}/>
27
28
  <div class="title">iframe</div>
28
29
  </header>
29
- <Input placeholder="url" fullWidth bind:value={iframe} autofocus
30
- on:submit={() => $tiptap.commands.insertContent({type: 'iframe', attrs: {src: iframe}})}/>
30
+ <Input placeholder="url" fullWidth bind:value={iframe} bind:input={focus}
31
+ on:submit={() => $tiptap.chain().focus().insertContent({type: 'iframe', attrs: {src: iframe}}).insertContent('\n').run()}/>
31
32
  <footer>
32
33
  <Button tabindex="0" transparent small on:click={() => {
33
- iframe = ''
34
- $slashDetail = ''
35
- }}>{i18n('cancel')}
34
+ iframe = ''
35
+ $slashDetail = ''
36
+ }}>{i18n('cancel')}
36
37
  </Button>
37
38
  <Button tabindex="0" transparent small
38
- on:click={() => $tiptap.commands.insertContent({type: 'iframe', attrs: {src: iframe}})}>{i18n('insert')}
39
+ on:click={() => {
40
+ $slashSelection?.();
41
+ $tiptap.chain().focus().insertContent({type: 'iframe', attrs: {src: iframe}}).insertContent('\n').run();
42
+ }}>{i18n('insert')}
39
43
  </Button>
40
44
  </footer>
41
45
  </div>
@@ -45,31 +49,52 @@ $: if ($slashVisible) {
45
49
  <IconButton icon="arrow_back" on:click={() => $slashDetail = ''}/>
46
50
  <div class="title">Youtube</div>
47
51
  </header>
48
- <Input placeholder="url" fullWidth bind:value={iframe} autofocus
49
- on:submit={() => $tiptap.commands.insertVideoPlayer({url: iframe})}/>
52
+ <Input placeholder="url" fullWidth bind:value={iframe} bind:input={focus}
53
+ on:submit={() => $tiptap.chain().focus().insertVideoPlayer({url: iframe}).insertContent('\n').run()}/>
50
54
  <footer>
51
55
  <Button tabindex="0" transparent small on:click={() => {
52
- iframe = ''
53
- $slashDetail = ''
54
- }}>{i18n('cancel')}
56
+ iframe = ''
57
+ $slashDetail = ''
58
+ }}>{i18n('cancel')}
55
59
  </Button>
56
- <Button tabindex="0" transparent small
57
- on:click={() => $tiptap.commands.insertVideoPlayer({url: iframe})}>{i18n('insert')}
60
+ <Button tabindex="0" transparent small on:click={() => {
61
+ $slashSelection?.();
62
+ $tiptap.chain().focus().insertVideoPlayer({url: iframe}).insertContent('\n').run();
63
+ }}>{i18n('insert')}
58
64
  </Button>
59
65
  </footer>
60
66
  </div>
67
+ {:else if $slashDetail === 'emoji'}
68
+ <div class="list">
69
+ <List>
70
+ {#each $slashItems as {title, command}, i(title)}
71
+ <div transition:slide={{duration: 400, easing: quartOut}}>
72
+ <OneLine on:click={() => {
73
+ command?.($slashProps);
74
+ setTimeout(() => $tiptap.commands.focus());
75
+ }} bind:this={elements[i]} {title} active={selectedIndex === i}/>
76
+ </div>
77
+ {/each}
78
+ {#if !$slashItems.length}
79
+ <div class="section"
80
+ transition:slide={{duration: 400, easing: quartOut}}>{i18n('noResult')}</div>
81
+ {/if}
82
+ </List>
83
+ </div>
61
84
  {:else}
62
85
  <div class="list">
63
86
  <List>
64
- {#each $slashItems as {section, list}(section)}
87
+ {#each $slashItems as {section, list}, j(section)}
88
+ {@const lastCount = $slashItems.slice(0, j).reduce((acc, cur) => acc + cur.list.length, 0)}
65
89
  <div class="section" transition:slide={{duration: 400, easing: quartOut}}>{section}</div>
66
90
  <div transition:slide={{duration: 400, easing: quartOut}}>
67
91
  {#each list || [] as {title, subtitle, icon, command, section}, i(title)}
68
92
  <div transition:slide={{duration: 400, easing: quartOut}}>
69
- <TwoLine on:mouseenter={() => (selectedIndex = i)} on:click={() => {
93
+ <TwoLine on:mouseenter={() => (selectedIndex = i + lastCount)} on:click={() => {
70
94
  command?.($slashProps);
71
95
  setTimeout(() => $tiptap.commands.focus());
72
- }} bind:this={elements[i]} {icon} {title} subtitle={subtitle || ''}/>
96
+ }} bind:this={elements[i + lastCount]} {icon} {title} subtitle={subtitle || ''}
97
+ active={selectedIndex === i + lastCount}/>
73
98
  </div>
74
99
  {/each}
75
100
  </div>
@@ -23,11 +23,13 @@ const san = (body) => sanitizeHtml(body, {
23
23
  },
24
24
  });
25
25
  export let body = '', editable = false, ref = null, options = {};
26
- export const imageUpload = fallbackUpload, style = '';
26
+ export let imageUpload = fallbackUpload, style = '';
27
+ export let blocks = [];
27
28
  const tiptap = setContext('editor', writable(null));
28
29
  let element, fullscreen = false, mounted = false, last = '';
29
30
  $: $tiptap && $tiptap.setEditable(editable);
30
31
  $: browser && (window.__image_uploader = imageUpload);
32
+ $: browser && (window.__tiptap_blocks = blocks);
31
33
  if (browser) {
32
34
  onMount(() => {
33
35
  body = last = san(body);
@@ -64,14 +66,17 @@ $: selectedIndex = $slashVisible ? selectedIndex : 0;
64
66
  function handleKeydown(event) {
65
67
  if (!$slashVisible)
66
68
  return;
69
+ let count = $slashItems.length;
70
+ if ($slashItems[0]?.list)
71
+ count = $slashItems.reduce((acc, item) => acc + item.list.length, 0);
67
72
  if (event.key === 'ArrowUp') {
68
73
  event.preventDefault();
69
- selectedIndex = (selectedIndex + $slashItems.length - 1) % $slashItems.length;
74
+ selectedIndex = (selectedIndex + count - 1) % count;
70
75
  return true;
71
76
  }
72
77
  if (event.key === 'ArrowDown') {
73
78
  event.preventDefault();
74
- selectedIndex = (selectedIndex + 1) % $slashItems.length;
79
+ selectedIndex = (selectedIndex + 1) % count;
75
80
  return true;
76
81
  }
77
82
  if (event.key === 'Enter') {
@@ -82,10 +87,10 @@ function handleKeydown(event) {
82
87
  return false;
83
88
  }
84
89
  function selectItem(index) {
85
- const item = $slashItems[index];
90
+ const item = $slashItems[0]?.list ? $slashItems.map(i => i.list).flat()[index] : $slashItems[index];
86
91
  if (item) {
87
92
  let range = $slashProps.range;
88
- item.command({ editor: editable, range });
93
+ item.command({ editor: $tiptap, range });
89
94
  }
90
95
  }
91
96
  </script>
@@ -8,7 +8,8 @@ declare const __propDef: {
8
8
  ref?: null | undefined;
9
9
  options?: {} | undefined;
10
10
  imageUpload?: UploadFn | undefined;
11
- style?: "" | undefined;
11
+ style?: string | undefined;
12
+ blocks?: any[] | undefined;
12
13
  };
13
14
  events: {
14
15
  [evt: string]: CustomEvent<any>;
@@ -21,7 +22,5 @@ export type TipTapProps = typeof __propDef.props;
21
22
  export type TipTapEvents = typeof __propDef.events;
22
23
  export type TipTapSlots = typeof __propDef.slots;
23
24
  export default class TipTap extends SvelteComponentTyped<TipTapProps, TipTapEvents, TipTapSlots> {
24
- get imageUpload(): UploadFn;
25
- get style(): "";
26
25
  }
27
26
  export {};
@@ -23,55 +23,60 @@ import Iframe from "../plugin/iframe";
23
23
  // @ts-ignore
24
24
  import { MathInline, MathBlock } from "@seorii/prosemirror-math/tiptap";
25
25
  import Youtube from "../plugin/youtube";
26
- import command from "../plugin/command";
27
- export default (element, content, { plugins = [], ...props } = {}) => new Editor({
28
- element, content, ...props,
29
- extensions: [
30
- CodeBlockLowlight.extend({
31
- addKeyboardShortcuts() {
32
- return {
33
- ...this.parent?.(),
34
- 'Tab': () => {
35
- if (this.editor.isActive('codeBlock')) {
36
- return this.editor.commands.insertContent(' ');
26
+ import command from "../plugin/command/suggest";
27
+ import emoji from "../plugin/command/emoji";
28
+ export default (element, content, { plugins = [], ...props } = {}) => {
29
+ const tt = new Editor({
30
+ element, content, ...props,
31
+ extensions: [
32
+ CodeBlockLowlight.extend({
33
+ addKeyboardShortcuts() {
34
+ return {
35
+ ...this.parent?.(),
36
+ 'Tab': () => {
37
+ if (this.editor.isActive('codeBlock')) {
38
+ return this.editor.commands.insertContent(' ');
39
+ }
40
+ return true;
37
41
  }
38
- return true;
39
- }
40
- };
41
- }
42
- }).configure({ lowlight }),
43
- Image,
44
- Youtube,
45
- StarterKit,
46
- Underline,
47
- Highlight.configure({ multicolor: true }),
48
- Link.configure({
49
- openOnClick: true, protocols: ['ftp', 'mailto', {
50
- scheme: 'tel',
51
- optionalSlashes: true
52
- }]
53
- }),
54
- TextAlign.configure({ types: ['heading', 'paragraph', 'image'] }),
55
- DropCursor,
56
- orderedlist,
57
- MathInline,
58
- MathBlock,
59
- table,
60
- tableHeader,
61
- tableRow,
62
- tableCell,
63
- Superscript,
64
- Subscript,
65
- Indent,
66
- Color,
67
- TextStyle,
68
- Iframe,
69
- Code.extend({
70
- renderHTML({ HTMLAttributes }) {
71
- return ['code', mergeAttributes(HTMLAttributes, { class: 'inline' })];
72
- }
73
- }),
74
- command,
75
- ...plugins,
76
- ],
77
- });
42
+ };
43
+ }
44
+ }).configure({ lowlight }),
45
+ Image,
46
+ Youtube,
47
+ StarterKit,
48
+ Underline,
49
+ Highlight.configure({ multicolor: true }),
50
+ Link.configure({
51
+ openOnClick: true, protocols: ['ftp', 'mailto', {
52
+ scheme: 'tel',
53
+ optionalSlashes: true
54
+ }]
55
+ }),
56
+ TextAlign.configure({ types: ['heading', 'paragraph', 'image'] }),
57
+ DropCursor,
58
+ orderedlist,
59
+ MathInline,
60
+ MathBlock,
61
+ table,
62
+ tableHeader,
63
+ tableRow,
64
+ tableCell,
65
+ Superscript,
66
+ Subscript,
67
+ Indent,
68
+ Color,
69
+ TextStyle,
70
+ Iframe,
71
+ Code.extend({
72
+ renderHTML({ HTMLAttributes }) {
73
+ return ['code', mergeAttributes(HTMLAttributes, { class: 'inline' })];
74
+ }
75
+ }),
76
+ ...plugins,
77
+ ],
78
+ });
79
+ tt.registerPlugin(emoji(tt));
80
+ tt.registerPlugin(command(tt));
81
+ return tt;
82
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seorii/tiptap",
3
- "version": "0.1.2",
3
+ "version": "0.2.1",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "svelte-kit sync && svelte-package",
@@ -60,6 +60,8 @@
60
60
  "@tiptap/pm": "^2.0.4",
61
61
  "@tiptap/starter-kit": "^2.0.4",
62
62
  "@tiptap/suggestion": "^2.0.4",
63
+ "emojis-keywords": "2.0.0",
64
+ "emojis-list": "2.0.0",
63
65
  "lowlight": "^2.9.0",
64
66
  "nunui": "^0.0.101",
65
67
  "prosemirror-commands": "^1.5.2",
@@ -1,4 +0,0 @@
1
- import { Extension } from '@tiptap/core';
2
- export declare const Command: Extension<any, any>;
3
- declare const _default: Extension<any, any>;
4
- export default _default;
@@ -1,27 +0,0 @@
1
- import { Extension } from '@tiptap/core';
2
- import Suggestion from '@tiptap/suggestion';
3
- import suggestion from "./suggest";
4
- export const Command = Extension.create({
5
- name: 'slash',
6
- addOptions() {
7
- return {
8
- suggestion: {
9
- char: '/',
10
- command: ({ editor, range, props }) => {
11
- props.command({ editor, range });
12
- }
13
- }
14
- };
15
- },
16
- addProseMirrorPlugins() {
17
- return [
18
- Suggestion({
19
- editor: this.editor,
20
- ...this.options.suggestion
21
- })
22
- ];
23
- }
24
- });
25
- export default Command.configure({
26
- suggestion
27
- });
@@ -1,6 +0,0 @@
1
- $highlight-color: #00bcd4;
2
-
3
- .ProseMirror {
4
- --highlight-color: #{$highlight-color};
5
- --highlight-bg-color: #{$highlight-color}33;
6
- }