@akinon/ui-editor 1.0.2 → 1.0.4
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.
- package/dist/cjs/tiptap/components/__tests__/html-code-viewer.test.js +79 -3
- package/dist/cjs/tiptap/components/__tests__/html-code-viewer.test.tsx +106 -3
- package/dist/cjs/tiptap/components/__tests__/tiptap.test.js +42 -4
- package/dist/cjs/tiptap/components/__tests__/tiptap.test.tsx +57 -7
- package/dist/cjs/tiptap/components/format-bubble-menu.d.ts.map +1 -1
- package/dist/cjs/tiptap/components/format-bubble-menu.js +6 -5
- package/dist/cjs/tiptap/components/html-code-viewer.d.ts +2 -1
- package/dist/cjs/tiptap/components/html-code-viewer.d.ts.map +1 -1
- package/dist/cjs/tiptap/components/html-code-viewer.js +62 -22
- package/dist/cjs/tiptap/components/image-upload-placeholder.d.ts.map +1 -1
- package/dist/cjs/tiptap/components/image-upload-placeholder.js +5 -2
- package/dist/cjs/tiptap/components/secure-script-component.d.ts.map +1 -1
- package/dist/cjs/tiptap/components/secure-script-component.js +2 -5
- package/dist/cjs/tiptap/components/tiptap.d.ts +1 -1
- package/dist/cjs/tiptap/components/tiptap.d.ts.map +1 -1
- package/dist/cjs/tiptap/components/tiptap.js +84 -56
- package/dist/cjs/tiptap/constants/editor-config.d.ts +10 -1
- package/dist/cjs/tiptap/constants/editor-config.d.ts.map +1 -1
- package/dist/cjs/tiptap/constants/editor-config.js +11 -2
- package/dist/cjs/tiptap/constants/html-elements.d.ts +1 -0
- package/dist/cjs/tiptap/constants/html-elements.d.ts.map +1 -1
- package/dist/cjs/tiptap/constants/html-elements.js +2 -1
- package/dist/cjs/tiptap/extensions/comment-extension.d.ts.map +1 -1
- package/dist/cjs/tiptap/extensions/comment-extension.js +3 -3
- package/dist/cjs/tiptap/extensions/custom-table-cell-extension.d.ts.map +1 -1
- package/dist/cjs/tiptap/extensions/custom-table-cell-extension.js +11 -2
- package/dist/cjs/tiptap/extensions/custom-table-header-extension.d.ts.map +1 -1
- package/dist/cjs/tiptap/extensions/custom-table-header-extension.js +11 -2
- package/dist/cjs/tiptap/extensions/html-block-extension.d.ts.map +1 -1
- package/dist/cjs/tiptap/extensions/html-block-extension.js +11 -14
- package/dist/cjs/tiptap/extensions/html-inline-extension.d.ts.map +1 -1
- package/dist/cjs/tiptap/extensions/html-inline-extension.js +11 -14
- package/dist/cjs/tiptap/types/index.d.ts +12 -5
- package/dist/cjs/tiptap/types/index.d.ts.map +1 -1
- package/dist/cjs/tiptap/utils/__tests__/clean-html.test.d.ts +2 -0
- package/dist/cjs/tiptap/utils/__tests__/clean-html.test.d.ts.map +1 -0
- package/dist/cjs/tiptap/utils/__tests__/clean-html.test.js +93 -0
- package/dist/cjs/tiptap/utils/__tests__/clean-html.test.ts +129 -0
- package/dist/cjs/tiptap/utils/__tests__/data-attributes-helper.test.d.ts +2 -0
- package/dist/cjs/tiptap/utils/__tests__/data-attributes-helper.test.d.ts.map +1 -0
- package/dist/cjs/tiptap/utils/__tests__/data-attributes-helper.test.js +105 -0
- package/dist/cjs/tiptap/utils/__tests__/data-attributes-helper.test.ts +148 -0
- package/dist/cjs/tiptap/utils/__tests__/index.test.js +0 -2
- package/dist/cjs/tiptap/utils/__tests__/index.test.ts +0 -2
- package/dist/cjs/tiptap/utils/__tests__/prettier-format.test.d.ts +2 -0
- package/dist/cjs/tiptap/utils/__tests__/prettier-format.test.d.ts.map +1 -0
- package/dist/cjs/tiptap/utils/__tests__/prettier-format.test.js +33 -0
- package/dist/cjs/tiptap/utils/__tests__/prettier-format.test.ts +49 -0
- package/dist/cjs/tiptap/utils/__tests__/tiptap-extensions.test.js +157 -0
- package/dist/cjs/tiptap/utils/__tests__/tiptap-extensions.test.ts +234 -0
- package/dist/cjs/tiptap/utils/clean-html.d.ts +9 -0
- package/dist/cjs/tiptap/utils/clean-html.d.ts.map +1 -0
- package/dist/cjs/tiptap/utils/clean-html.js +75 -0
- package/dist/cjs/tiptap/utils/data-attributes-helper.d.ts +20 -0
- package/dist/cjs/tiptap/utils/data-attributes-helper.d.ts.map +1 -0
- package/dist/cjs/tiptap/utils/data-attributes-helper.js +68 -0
- package/dist/cjs/tiptap/utils/index.d.ts +3 -2
- package/dist/cjs/tiptap/utils/index.d.ts.map +1 -1
- package/dist/cjs/tiptap/utils/index.js +3 -2
- package/dist/cjs/tiptap/utils/prettier-format.d.ts +8 -0
- package/dist/cjs/tiptap/utils/prettier-format.d.ts.map +1 -0
- package/dist/cjs/tiptap/utils/prettier-format.js +26 -0
- package/dist/cjs/tiptap/utils/tiptap-extensions.d.ts.map +1 -1
- package/dist/cjs/tiptap/utils/tiptap-extensions.js +134 -14
- package/dist/esm/tiptap/components/__tests__/html-code-viewer.test.js +79 -3
- package/dist/esm/tiptap/components/__tests__/html-code-viewer.test.tsx +106 -3
- package/dist/esm/tiptap/components/__tests__/tiptap.test.js +42 -4
- package/dist/esm/tiptap/components/__tests__/tiptap.test.tsx +57 -7
- package/dist/esm/tiptap/components/format-bubble-menu.d.ts.map +1 -1
- package/dist/esm/tiptap/components/format-bubble-menu.js +6 -5
- package/dist/esm/tiptap/components/html-code-viewer.d.ts +2 -1
- package/dist/esm/tiptap/components/html-code-viewer.d.ts.map +1 -1
- package/dist/esm/tiptap/components/html-code-viewer.js +62 -22
- package/dist/esm/tiptap/components/image-upload-placeholder.d.ts.map +1 -1
- package/dist/esm/tiptap/components/image-upload-placeholder.js +5 -2
- package/dist/esm/tiptap/components/secure-script-component.d.ts.map +1 -1
- package/dist/esm/tiptap/components/secure-script-component.js +2 -5
- package/dist/esm/tiptap/components/tiptap.d.ts +1 -1
- package/dist/esm/tiptap/components/tiptap.d.ts.map +1 -1
- package/dist/esm/tiptap/components/tiptap.js +84 -56
- package/dist/esm/tiptap/constants/editor-config.d.ts +10 -1
- package/dist/esm/tiptap/constants/editor-config.d.ts.map +1 -1
- package/dist/esm/tiptap/constants/editor-config.js +11 -2
- package/dist/esm/tiptap/constants/html-elements.d.ts +1 -0
- package/dist/esm/tiptap/constants/html-elements.d.ts.map +1 -1
- package/dist/esm/tiptap/constants/html-elements.js +2 -1
- package/dist/esm/tiptap/extensions/comment-extension.d.ts.map +1 -1
- package/dist/esm/tiptap/extensions/comment-extension.js +3 -3
- package/dist/esm/tiptap/extensions/custom-table-cell-extension.d.ts.map +1 -1
- package/dist/esm/tiptap/extensions/custom-table-cell-extension.js +11 -2
- package/dist/esm/tiptap/extensions/custom-table-header-extension.d.ts.map +1 -1
- package/dist/esm/tiptap/extensions/custom-table-header-extension.js +11 -2
- package/dist/esm/tiptap/extensions/html-block-extension.d.ts.map +1 -1
- package/dist/esm/tiptap/extensions/html-block-extension.js +11 -14
- package/dist/esm/tiptap/extensions/html-inline-extension.d.ts.map +1 -1
- package/dist/esm/tiptap/extensions/html-inline-extension.js +11 -14
- package/dist/esm/tiptap/types/index.d.ts +12 -5
- package/dist/esm/tiptap/types/index.d.ts.map +1 -1
- package/dist/esm/tiptap/utils/__tests__/clean-html.test.d.ts +2 -0
- package/dist/esm/tiptap/utils/__tests__/clean-html.test.d.ts.map +1 -0
- package/dist/esm/tiptap/utils/__tests__/clean-html.test.js +93 -0
- package/dist/esm/tiptap/utils/__tests__/clean-html.test.ts +129 -0
- package/dist/esm/tiptap/utils/__tests__/data-attributes-helper.test.d.ts +2 -0
- package/dist/esm/tiptap/utils/__tests__/data-attributes-helper.test.d.ts.map +1 -0
- package/dist/esm/tiptap/utils/__tests__/data-attributes-helper.test.js +105 -0
- package/dist/esm/tiptap/utils/__tests__/data-attributes-helper.test.ts +148 -0
- package/dist/esm/tiptap/utils/__tests__/index.test.js +0 -2
- package/dist/esm/tiptap/utils/__tests__/index.test.ts +0 -2
- package/dist/esm/tiptap/utils/__tests__/prettier-format.test.d.ts +2 -0
- package/dist/esm/tiptap/utils/__tests__/prettier-format.test.d.ts.map +1 -0
- package/dist/esm/tiptap/utils/__tests__/prettier-format.test.js +33 -0
- package/dist/esm/tiptap/utils/__tests__/prettier-format.test.ts +49 -0
- package/dist/esm/tiptap/utils/__tests__/tiptap-extensions.test.js +157 -0
- package/dist/esm/tiptap/utils/__tests__/tiptap-extensions.test.ts +234 -0
- package/dist/esm/tiptap/utils/clean-html.d.ts +9 -0
- package/dist/esm/tiptap/utils/clean-html.d.ts.map +1 -0
- package/dist/esm/tiptap/utils/clean-html.js +75 -0
- package/dist/esm/tiptap/utils/data-attributes-helper.d.ts +20 -0
- package/dist/esm/tiptap/utils/data-attributes-helper.d.ts.map +1 -0
- package/dist/esm/tiptap/utils/data-attributes-helper.js +68 -0
- package/dist/esm/tiptap/utils/index.d.ts +3 -2
- package/dist/esm/tiptap/utils/index.d.ts.map +1 -1
- package/dist/esm/tiptap/utils/index.js +3 -2
- package/dist/esm/tiptap/utils/prettier-format.d.ts +8 -0
- package/dist/esm/tiptap/utils/prettier-format.d.ts.map +1 -0
- package/dist/esm/tiptap/utils/prettier-format.js +26 -0
- package/dist/esm/tiptap/utils/tiptap-extensions.d.ts.map +1 -1
- package/dist/esm/tiptap/utils/tiptap-extensions.js +134 -14
- package/package.json +13 -12
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import '@testing-library/jest-dom';
|
|
2
|
-
import { fireEvent, render, screen } from '@testing-library/react';
|
|
2
|
+
import { createEvent, fireEvent, render, screen, waitFor } from '@testing-library/react';
|
|
3
3
|
import { ConfigProvider } from 'antd';
|
|
4
4
|
import React from 'react';
|
|
5
5
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
6
|
+
import { formatHtmlWithPrettier } from '../../utils';
|
|
6
7
|
import { HtmlCodeViewer } from '../html-code-viewer';
|
|
7
8
|
vi.mock('@ant-design/cssinjs', () => ({
|
|
8
9
|
useStyleRegister: vi.fn((_config, cb) => {
|
|
@@ -11,7 +12,14 @@ vi.mock('@ant-design/cssinjs', () => ({
|
|
|
11
12
|
})
|
|
12
13
|
}));
|
|
13
14
|
vi.mock('@akinon/ui-theme', () => ({
|
|
14
|
-
useToken: () => ({ token: {}, hashId: 'hash-id' })
|
|
15
|
+
useToken: () => ({ token: {}, hashId: 'hash-id' }),
|
|
16
|
+
getSafeCustomTokens: vi.fn(() => ({
|
|
17
|
+
border: { borderWidthThick: '2px', borderSolid: 'solid' }
|
|
18
|
+
}))
|
|
19
|
+
}));
|
|
20
|
+
vi.mock('../../utils', () => ({
|
|
21
|
+
highlightHtml: (html) => html,
|
|
22
|
+
formatHtmlWithPrettier: vi.fn((html) => Promise.resolve(html))
|
|
15
23
|
}));
|
|
16
24
|
describe('HtmlCodeViewer', () => {
|
|
17
25
|
const defaultProps = {
|
|
@@ -76,7 +84,11 @@ describe('HtmlCodeViewer', () => {
|
|
|
76
84
|
neutral: {
|
|
77
85
|
'50': '#fff',
|
|
78
86
|
'1000': '#000'
|
|
79
|
-
}
|
|
87
|
+
},
|
|
88
|
+
red: { '825': '#f00', '999': '#a00', '815': '#d00' },
|
|
89
|
+
blue: { '999': '#00f' },
|
|
90
|
+
green: { '825': '#0f0' },
|
|
91
|
+
ebonyClay: { '550': '#123' }
|
|
80
92
|
}
|
|
81
93
|
};
|
|
82
94
|
render(
|
|
@@ -86,4 +98,68 @@ describe('HtmlCodeViewer', () => {
|
|
|
86
98
|
const textarea = screen.getByRole('textbox');
|
|
87
99
|
expect(textarea).toBeInTheDocument();
|
|
88
100
|
});
|
|
101
|
+
it('should format code on mount', async () => {
|
|
102
|
+
const formatted = '<p> Formatted </p>';
|
|
103
|
+
vi.mocked(formatHtmlWithPrettier).mockResolvedValue(formatted);
|
|
104
|
+
render(React.createElement(HtmlCodeViewer, Object.assign({}, defaultProps, { value: "<p>Raw</p>" })));
|
|
105
|
+
await waitFor(() => {
|
|
106
|
+
expect(defaultProps.onChange).toHaveBeenCalledWith(formatted);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
it('should handle paste event', async () => {
|
|
110
|
+
const formatted = '<p>Formatted Paste</p>';
|
|
111
|
+
vi.mocked(formatHtmlWithPrettier).mockResolvedValue(formatted);
|
|
112
|
+
render(React.createElement(HtmlCodeViewer, Object.assign({}, defaultProps, { readOnly: false })));
|
|
113
|
+
const textarea = screen.getByRole('textbox');
|
|
114
|
+
const pasteData = 'Pasted Text';
|
|
115
|
+
const pasteEvent = createEvent.paste(textarea, {
|
|
116
|
+
clipboardData: {
|
|
117
|
+
getData: vi.fn().mockReturnValue(pasteData)
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
121
|
+
pasteEvent.preventDefault = vi.fn();
|
|
122
|
+
fireEvent(textarea, pasteEvent);
|
|
123
|
+
await waitFor(() => {
|
|
124
|
+
var _a;
|
|
125
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
126
|
+
expect(pasteEvent.preventDefault).toHaveBeenCalled();
|
|
127
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
128
|
+
expect((_a = pasteEvent.clipboardData) === null || _a === void 0 ? void 0 : _a.getData).toHaveBeenCalledWith('text/plain');
|
|
129
|
+
expect(formatHtmlWithPrettier).toHaveBeenCalled();
|
|
130
|
+
expect(defaultProps.onChange).toHaveBeenCalledWith(formatted);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
it('should not handle paste event if readOnly is true', () => {
|
|
134
|
+
render(React.createElement(HtmlCodeViewer, Object.assign({}, defaultProps, { readOnly: true })));
|
|
135
|
+
const textarea = screen.getByRole('textbox');
|
|
136
|
+
const pasteEvent = createEvent.paste(textarea, {
|
|
137
|
+
clipboardData: {
|
|
138
|
+
getData: vi.fn().mockReturnValue('Some Text')
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
142
|
+
pasteEvent.preventDefault = vi.fn();
|
|
143
|
+
fireEvent(textarea, pasteEvent);
|
|
144
|
+
expect(formatHtmlWithPrettier).not.toHaveBeenCalled();
|
|
145
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
146
|
+
expect(pasteEvent.preventDefault).not.toHaveBeenCalled();
|
|
147
|
+
});
|
|
148
|
+
it('should not handle paste event if clipboard text is empty', () => {
|
|
149
|
+
render(React.createElement(HtmlCodeViewer, Object.assign({}, defaultProps)));
|
|
150
|
+
// Clear mock because formatOnMount triggers it
|
|
151
|
+
vi.mocked(formatHtmlWithPrettier).mockClear();
|
|
152
|
+
const textarea = screen.getByRole('textbox');
|
|
153
|
+
const pasteEvent = createEvent.paste(textarea, {
|
|
154
|
+
clipboardData: {
|
|
155
|
+
getData: vi.fn().mockReturnValue('')
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
159
|
+
pasteEvent.preventDefault = vi.fn();
|
|
160
|
+
fireEvent(textarea, pasteEvent);
|
|
161
|
+
expect(formatHtmlWithPrettier).not.toHaveBeenCalled();
|
|
162
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
163
|
+
expect(pasteEvent.preventDefault).toHaveBeenCalled(); // preventDefault is called before check? No, line 83 calls preventDefault.
|
|
164
|
+
});
|
|
89
165
|
});
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import '@testing-library/jest-dom';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
createEvent,
|
|
5
|
+
fireEvent,
|
|
6
|
+
render,
|
|
7
|
+
screen,
|
|
8
|
+
waitFor
|
|
9
|
+
} from '@testing-library/react';
|
|
4
10
|
import { ConfigProvider } from 'antd';
|
|
5
11
|
import React from 'react';
|
|
6
12
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
7
13
|
|
|
14
|
+
import { formatHtmlWithPrettier } from '../../utils';
|
|
8
15
|
import { HtmlCodeViewer } from '../html-code-viewer';
|
|
9
16
|
|
|
10
17
|
vi.mock('@ant-design/cssinjs', () => ({
|
|
@@ -15,7 +22,15 @@ vi.mock('@ant-design/cssinjs', () => ({
|
|
|
15
22
|
}));
|
|
16
23
|
|
|
17
24
|
vi.mock('@akinon/ui-theme', () => ({
|
|
18
|
-
useToken: () => ({ token: {}, hashId: 'hash-id' })
|
|
25
|
+
useToken: () => ({ token: {}, hashId: 'hash-id' }),
|
|
26
|
+
getSafeCustomTokens: vi.fn(() => ({
|
|
27
|
+
border: { borderWidthThick: '2px', borderSolid: 'solid' }
|
|
28
|
+
}))
|
|
29
|
+
}));
|
|
30
|
+
|
|
31
|
+
vi.mock('../../utils', () => ({
|
|
32
|
+
highlightHtml: (html: string) => html,
|
|
33
|
+
formatHtmlWithPrettier: vi.fn((html: string) => Promise.resolve(html))
|
|
19
34
|
}));
|
|
20
35
|
|
|
21
36
|
describe('HtmlCodeViewer', () => {
|
|
@@ -109,7 +124,11 @@ describe('HtmlCodeViewer', () => {
|
|
|
109
124
|
neutral: {
|
|
110
125
|
'50': '#fff',
|
|
111
126
|
'1000': '#000'
|
|
112
|
-
}
|
|
127
|
+
},
|
|
128
|
+
red: { '825': '#f00', '999': '#a00', '815': '#d00' },
|
|
129
|
+
blue: { '999': '#00f' },
|
|
130
|
+
green: { '825': '#0f0' },
|
|
131
|
+
ebonyClay: { '550': '#123' }
|
|
113
132
|
}
|
|
114
133
|
};
|
|
115
134
|
|
|
@@ -123,4 +142,88 @@ describe('HtmlCodeViewer', () => {
|
|
|
123
142
|
const textarea = screen.getByRole('textbox');
|
|
124
143
|
expect(textarea).toBeInTheDocument();
|
|
125
144
|
});
|
|
145
|
+
|
|
146
|
+
it('should format code on mount', async () => {
|
|
147
|
+
const formatted = '<p> Formatted </p>';
|
|
148
|
+
vi.mocked(formatHtmlWithPrettier).mockResolvedValue(formatted);
|
|
149
|
+
|
|
150
|
+
render(<HtmlCodeViewer {...defaultProps} value="<p>Raw</p>" />);
|
|
151
|
+
|
|
152
|
+
await waitFor(() => {
|
|
153
|
+
expect(defaultProps.onChange).toHaveBeenCalledWith(formatted);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('should handle paste event', async () => {
|
|
158
|
+
const formatted = '<p>Formatted Paste</p>';
|
|
159
|
+
vi.mocked(formatHtmlWithPrettier).mockResolvedValue(formatted);
|
|
160
|
+
|
|
161
|
+
render(<HtmlCodeViewer {...defaultProps} readOnly={false} />);
|
|
162
|
+
const textarea = screen.getByRole('textbox');
|
|
163
|
+
|
|
164
|
+
const pasteData = 'Pasted Text';
|
|
165
|
+
|
|
166
|
+
const pasteEvent = createEvent.paste(textarea, {
|
|
167
|
+
clipboardData: {
|
|
168
|
+
getData: vi.fn().mockReturnValue(pasteData)
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
173
|
+
(pasteEvent as any).preventDefault = vi.fn();
|
|
174
|
+
|
|
175
|
+
fireEvent(textarea, pasteEvent);
|
|
176
|
+
|
|
177
|
+
await waitFor(() => {
|
|
178
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
179
|
+
expect((pasteEvent as any).preventDefault).toHaveBeenCalled();
|
|
180
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
181
|
+
expect((pasteEvent as any).clipboardData?.getData).toHaveBeenCalledWith(
|
|
182
|
+
'text/plain'
|
|
183
|
+
);
|
|
184
|
+
expect(formatHtmlWithPrettier).toHaveBeenCalled();
|
|
185
|
+
expect(defaultProps.onChange).toHaveBeenCalledWith(formatted);
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it('should not handle paste event if readOnly is true', () => {
|
|
190
|
+
render(<HtmlCodeViewer {...defaultProps} readOnly={true} />);
|
|
191
|
+
const textarea = screen.getByRole('textbox');
|
|
192
|
+
|
|
193
|
+
const pasteEvent = createEvent.paste(textarea, {
|
|
194
|
+
clipboardData: {
|
|
195
|
+
getData: vi.fn().mockReturnValue('Some Text')
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
199
|
+
(pasteEvent as any).preventDefault = vi.fn();
|
|
200
|
+
|
|
201
|
+
fireEvent(textarea, pasteEvent);
|
|
202
|
+
|
|
203
|
+
expect(formatHtmlWithPrettier).not.toHaveBeenCalled();
|
|
204
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
205
|
+
expect((pasteEvent as any).preventDefault).not.toHaveBeenCalled();
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it('should not handle paste event if clipboard text is empty', () => {
|
|
209
|
+
render(<HtmlCodeViewer {...defaultProps} />);
|
|
210
|
+
// Clear mock because formatOnMount triggers it
|
|
211
|
+
vi.mocked(formatHtmlWithPrettier).mockClear();
|
|
212
|
+
|
|
213
|
+
const textarea = screen.getByRole('textbox');
|
|
214
|
+
|
|
215
|
+
const pasteEvent = createEvent.paste(textarea, {
|
|
216
|
+
clipboardData: {
|
|
217
|
+
getData: vi.fn().mockReturnValue('')
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
221
|
+
(pasteEvent as any).preventDefault = vi.fn();
|
|
222
|
+
|
|
223
|
+
fireEvent(textarea, pasteEvent);
|
|
224
|
+
|
|
225
|
+
expect(formatHtmlWithPrettier).not.toHaveBeenCalled();
|
|
226
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
227
|
+
expect((pasteEvent as any).preventDefault).toHaveBeenCalled(); // preventDefault is called before check? No, line 83 calls preventDefault.
|
|
228
|
+
});
|
|
126
229
|
});
|
|
@@ -9,6 +9,7 @@ const { mockUseEditor, mockChangeLanguage } = vi.hoisted(() => ({
|
|
|
9
9
|
mockUseEditor: vi.fn(),
|
|
10
10
|
mockChangeLanguage: vi.fn()
|
|
11
11
|
}));
|
|
12
|
+
vi.useFakeTimers();
|
|
12
13
|
vi.mock('@tiptap/react', () => ({
|
|
13
14
|
useEditor: mockUseEditor,
|
|
14
15
|
useEditorState: vi.fn(() => ({})),
|
|
@@ -42,8 +43,7 @@ vi.mock('../../assets/icons', () => ({
|
|
|
42
43
|
}));
|
|
43
44
|
vi.mock('../../utils', () => ({
|
|
44
45
|
getExtensions: vi.fn(() => []),
|
|
45
|
-
|
|
46
|
-
normalizeHtml: vi.fn(html => `normalized-${html}`)
|
|
46
|
+
cleanDuplicateSpans: vi.fn(html => html)
|
|
47
47
|
}));
|
|
48
48
|
vi.mock('@akinon/akilocale/react', () => ({
|
|
49
49
|
useTranslation: () => ({
|
|
@@ -53,7 +53,8 @@ vi.mock('@akinon/akilocale/react', () => ({
|
|
|
53
53
|
}));
|
|
54
54
|
vi.mock('@akinon/ui-theme', () => ({
|
|
55
55
|
getSafeCustomTokens: vi.fn(() => ({
|
|
56
|
-
typography: { fontWeightMedium: 500 }
|
|
56
|
+
typography: { fontWeightMedium: 500 },
|
|
57
|
+
border: { borderWidthThick: '2px', borderSolid: 'solid' }
|
|
57
58
|
})),
|
|
58
59
|
useToken: () => ({
|
|
59
60
|
token: { colorBorder: '#ccc' },
|
|
@@ -83,6 +84,10 @@ describe('Tiptap', () => {
|
|
|
83
84
|
}
|
|
84
85
|
};
|
|
85
86
|
mockUseEditor.mockReturnValue(mockEditor);
|
|
87
|
+
vi.useFakeTimers();
|
|
88
|
+
});
|
|
89
|
+
afterEach(() => {
|
|
90
|
+
vi.useRealTimers();
|
|
86
91
|
});
|
|
87
92
|
const renderComponent = (props = {}) => {
|
|
88
93
|
return render(React.createElement(Tiptap, Object.assign({ value: "<p>Test</p>", onChange: onChange }, props)));
|
|
@@ -116,7 +121,9 @@ describe('Tiptap', () => {
|
|
|
116
121
|
expect(screen.getByTestId('html-code-viewer')).toBeInTheDocument();
|
|
117
122
|
fireEvent.click(toggleButton);
|
|
118
123
|
expect(screen.getByTestId('editor-content')).toBeInTheDocument();
|
|
119
|
-
expect(mockEditor.commands.setContent).toHaveBeenCalledWith('
|
|
124
|
+
expect(mockEditor.commands.setContent).toHaveBeenCalledWith('<p>Test</p>', {
|
|
125
|
+
emitUpdate: false
|
|
126
|
+
});
|
|
120
127
|
fireEvent.click(toggleButton);
|
|
121
128
|
expect(screen.getByTestId('html-code-viewer')).toBeInTheDocument();
|
|
122
129
|
});
|
|
@@ -124,6 +131,7 @@ describe('Tiptap', () => {
|
|
|
124
131
|
renderComponent();
|
|
125
132
|
const viewer = screen.getByTestId('html-code-viewer');
|
|
126
133
|
fireEvent.change(viewer, { target: { value: '<p>New Content</p>' } });
|
|
134
|
+
vi.advanceTimersByTime(1000);
|
|
127
135
|
expect(onChange).toHaveBeenCalledWith({
|
|
128
136
|
html: '<p>New Content</p>',
|
|
129
137
|
json: expect.any(Object)
|
|
@@ -272,4 +280,34 @@ describe('Tiptap', () => {
|
|
|
272
280
|
expect(resultDiv).toBe(false);
|
|
273
281
|
expect(preventDefault).not.toHaveBeenCalled();
|
|
274
282
|
});
|
|
283
|
+
it('should debounce source code changes and clear previous timeout', () => {
|
|
284
|
+
renderComponent();
|
|
285
|
+
const viewer = screen.getByTestId('html-code-viewer');
|
|
286
|
+
fireEvent.change(viewer, { target: { value: '<p>Change 1</p>' } });
|
|
287
|
+
fireEvent.change(viewer, { target: { value: '<p>Change 2</p>' } });
|
|
288
|
+
vi.advanceTimersByTime(300);
|
|
289
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
290
|
+
html: '<p>Change 2</p>',
|
|
291
|
+
json: expect.any(Object)
|
|
292
|
+
});
|
|
293
|
+
expect(onChange).toHaveBeenCalledTimes(1);
|
|
294
|
+
});
|
|
295
|
+
it('should initialize with empty string if value and defaultValue are undefined', () => {
|
|
296
|
+
render(React.createElement(Tiptap, { onChange: onChange }));
|
|
297
|
+
const viewer = screen.getByTestId('html-code-viewer');
|
|
298
|
+
expect(viewer).toHaveValue('');
|
|
299
|
+
});
|
|
300
|
+
it('should remove type="text/inert" from script tags when switching to source mode', () => {
|
|
301
|
+
// Start in visual mode
|
|
302
|
+
render(React.createElement(Tiptap, { defaultSourceMode: false, onChange: onChange }));
|
|
303
|
+
// Mock editor.getHTML() to return content with inert script
|
|
304
|
+
mockEditor.getHTML.mockReturnValue('<script type="text/inert">console.log("test")</script>');
|
|
305
|
+
// Switch to source mode
|
|
306
|
+
const toggleButton = screen.getByTestId('toggle-source');
|
|
307
|
+
fireEvent.click(toggleButton);
|
|
308
|
+
// Verify source mode content (cleanDuplicateSpans is mocked to return input)
|
|
309
|
+
// The setRawHTML update triggers a re-render of HtmlCodeViewer
|
|
310
|
+
const viewer = screen.getByTestId('html-code-viewer');
|
|
311
|
+
expect(viewer).toHaveValue('<script>console.log("test")</script>');
|
|
312
|
+
});
|
|
275
313
|
});
|
|
@@ -13,6 +13,8 @@ const { mockUseEditor, mockChangeLanguage } = vi.hoisted(() => ({
|
|
|
13
13
|
mockChangeLanguage: vi.fn()
|
|
14
14
|
}));
|
|
15
15
|
|
|
16
|
+
vi.useFakeTimers();
|
|
17
|
+
|
|
16
18
|
vi.mock('@tiptap/react', () => ({
|
|
17
19
|
useEditor: mockUseEditor,
|
|
18
20
|
useEditorState: vi.fn(() => ({})),
|
|
@@ -71,8 +73,7 @@ vi.mock('../../assets/icons', () => ({
|
|
|
71
73
|
|
|
72
74
|
vi.mock('../../utils', () => ({
|
|
73
75
|
getExtensions: vi.fn(() => []),
|
|
74
|
-
|
|
75
|
-
normalizeHtml: vi.fn(html => `normalized-${html}`)
|
|
76
|
+
cleanDuplicateSpans: vi.fn(html => html)
|
|
76
77
|
}));
|
|
77
78
|
|
|
78
79
|
vi.mock('@akinon/akilocale/react', () => ({
|
|
@@ -84,7 +85,8 @@ vi.mock('@akinon/akilocale/react', () => ({
|
|
|
84
85
|
|
|
85
86
|
vi.mock('@akinon/ui-theme', () => ({
|
|
86
87
|
getSafeCustomTokens: vi.fn(() => ({
|
|
87
|
-
typography: { fontWeightMedium: 500 }
|
|
88
|
+
typography: { fontWeightMedium: 500 },
|
|
89
|
+
border: { borderWidthThick: '2px', borderSolid: 'solid' }
|
|
88
90
|
})),
|
|
89
91
|
useToken: () => ({
|
|
90
92
|
token: { colorBorder: '#ccc' },
|
|
@@ -118,6 +120,11 @@ describe('Tiptap', () => {
|
|
|
118
120
|
};
|
|
119
121
|
|
|
120
122
|
mockUseEditor.mockReturnValue(mockEditor);
|
|
123
|
+
vi.useFakeTimers();
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
afterEach(() => {
|
|
127
|
+
vi.useRealTimers();
|
|
121
128
|
});
|
|
122
129
|
|
|
123
130
|
const renderComponent = (props = {}) => {
|
|
@@ -161,10 +168,9 @@ describe('Tiptap', () => {
|
|
|
161
168
|
|
|
162
169
|
fireEvent.click(toggleButton);
|
|
163
170
|
expect(screen.getByTestId('editor-content')).toBeInTheDocument();
|
|
164
|
-
expect(mockEditor.commands.setContent).toHaveBeenCalledWith(
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
);
|
|
171
|
+
expect(mockEditor.commands.setContent).toHaveBeenCalledWith('<p>Test</p>', {
|
|
172
|
+
emitUpdate: false
|
|
173
|
+
});
|
|
168
174
|
|
|
169
175
|
fireEvent.click(toggleButton);
|
|
170
176
|
expect(screen.getByTestId('html-code-viewer')).toBeInTheDocument();
|
|
@@ -176,6 +182,8 @@ describe('Tiptap', () => {
|
|
|
176
182
|
|
|
177
183
|
fireEvent.change(viewer, { target: { value: '<p>New Content</p>' } });
|
|
178
184
|
|
|
185
|
+
vi.advanceTimersByTime(1000);
|
|
186
|
+
|
|
179
187
|
expect(onChange).toHaveBeenCalledWith({
|
|
180
188
|
html: '<p>New Content</p>',
|
|
181
189
|
json: expect.any(Object)
|
|
@@ -375,4 +383,46 @@ describe('Tiptap', () => {
|
|
|
375
383
|
expect(resultDiv).toBe(false);
|
|
376
384
|
expect(preventDefault).not.toHaveBeenCalled();
|
|
377
385
|
});
|
|
386
|
+
it('should debounce source code changes and clear previous timeout', () => {
|
|
387
|
+
renderComponent();
|
|
388
|
+
const viewer = screen.getByTestId('html-code-viewer');
|
|
389
|
+
|
|
390
|
+
fireEvent.change(viewer, { target: { value: '<p>Change 1</p>' } });
|
|
391
|
+
|
|
392
|
+
fireEvent.change(viewer, { target: { value: '<p>Change 2</p>' } });
|
|
393
|
+
|
|
394
|
+
vi.advanceTimersByTime(300);
|
|
395
|
+
|
|
396
|
+
expect(onChange).toHaveBeenCalledWith({
|
|
397
|
+
html: '<p>Change 2</p>',
|
|
398
|
+
json: expect.any(Object)
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
expect(onChange).toHaveBeenCalledTimes(1);
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
it('should initialize with empty string if value and defaultValue are undefined', () => {
|
|
405
|
+
render(<Tiptap onChange={onChange} />);
|
|
406
|
+
const viewer = screen.getByTestId('html-code-viewer');
|
|
407
|
+
expect(viewer).toHaveValue('');
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
it('should remove type="text/inert" from script tags when switching to source mode', () => {
|
|
411
|
+
// Start in visual mode
|
|
412
|
+
render(<Tiptap defaultSourceMode={false} onChange={onChange} />);
|
|
413
|
+
|
|
414
|
+
// Mock editor.getHTML() to return content with inert script
|
|
415
|
+
mockEditor.getHTML.mockReturnValue(
|
|
416
|
+
'<script type="text/inert">console.log("test")</script>'
|
|
417
|
+
);
|
|
418
|
+
|
|
419
|
+
// Switch to source mode
|
|
420
|
+
const toggleButton = screen.getByTestId('toggle-source');
|
|
421
|
+
fireEvent.click(toggleButton);
|
|
422
|
+
|
|
423
|
+
// Verify source mode content (cleanDuplicateSpans is mocked to return input)
|
|
424
|
+
// The setRawHTML update triggers a re-render of HtmlCodeViewer
|
|
425
|
+
const viewer = screen.getByTestId('html-code-viewer');
|
|
426
|
+
expect(viewer).toHaveValue('<script>console.log("test")</script>');
|
|
427
|
+
});
|
|
378
428
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format-bubble-menu.d.ts","sourceRoot":"","sources":["../../../../src/tiptap/components/format-bubble-menu.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAG5C,OAAO,KAA8B,MAAM,OAAO,CAAC;AAInD,UAAU,qBAAqB;IAC7B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,gBAAgB,GAAI,YAAY,qBAAqB,
|
|
1
|
+
{"version":3,"file":"format-bubble-menu.d.ts","sourceRoot":"","sources":["../../../../src/tiptap/components/format-bubble-menu.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAG5C,OAAO,KAA8B,MAAM,OAAO,CAAC;AAInD,UAAU,qBAAqB;IAC7B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,gBAAgB,GAAI,YAAY,qBAAqB,6BAmRjE,CAAC"}
|
|
@@ -164,6 +164,11 @@ export const FormatBubbleMenu = ({ editor }) => {
|
|
|
164
164
|
tooltip: i18n.t('editor.toolbar.link')
|
|
165
165
|
}
|
|
166
166
|
];
|
|
167
|
+
const handleOnInputKeyDown = (e) => {
|
|
168
|
+
if (e.key === 'Enter') {
|
|
169
|
+
handleApplyLink();
|
|
170
|
+
}
|
|
171
|
+
};
|
|
167
172
|
return useStyle(React.createElement(BubbleMenu, { editor: editor, pluginKey: "link-bubble-menu", options: { placement: 'bottom' }, shouldShow: ({ editor }) => {
|
|
168
173
|
if (!isTextSelection(editor.state.selection) ||
|
|
169
174
|
editor.isActive('table')) {
|
|
@@ -191,11 +196,7 @@ export const FormatBubbleMenu = ({ editor }) => {
|
|
|
191
196
|
return from !== to && editor.isFocused;
|
|
192
197
|
} },
|
|
193
198
|
React.createElement("div", { className: `${baseCls} ${hashId}` }, showLinkInput ? (React.createElement(React.Fragment, null,
|
|
194
|
-
React.createElement(Input, { type: "text", placeholder: i18n.t('editor.link.url_placeholder'), value: url, autoFocus: true, onChange: e => setUrl(e.target.value), onKeyDown:
|
|
195
|
-
if (e.key === 'Enter') {
|
|
196
|
-
handleApplyLink();
|
|
197
|
-
}
|
|
198
|
-
}, size: "small", className: `${baseCls}__link-input` }),
|
|
199
|
+
React.createElement(Input, { type: "text", placeholder: i18n.t('editor.link.url_placeholder'), value: url, autoFocus: true, onChange: e => setUrl(e.target.value), onKeyDown: handleOnInputKeyDown, size: "small", className: `${baseCls}__link-input` }),
|
|
199
200
|
React.createElement("div", { className: `${baseCls}__actions` },
|
|
200
201
|
React.createElement(Button, { size: "small", type: "success", icon: "katalogkontrol", onClick: handleApplyLink, disabled: !url, tooltip: i18n.t('editor.common.save') }),
|
|
201
202
|
React.createElement(Button, { size: "small", type: "default", danger: true, icon: "bin", onClick: handleRemoveLink, tooltip: i18n.t('editor.common.remove') })))) : (React.createElement("div", { className: `${baseCls}__actions` }, formattingButtons.map((btn, index) => (React.createElement(Button, { key: index, type: "icon", size: "small", onClick: btn.onClick, icon: btn.icon, className: btn.isActive ? activeCls : '', tooltip: btn.tooltip }))))))));
|
|
@@ -4,7 +4,8 @@ interface HtmlCodeViewerProps {
|
|
|
4
4
|
onChange: (value: string) => void;
|
|
5
5
|
className?: string;
|
|
6
6
|
readOnly?: boolean;
|
|
7
|
+
contentHeight?: number;
|
|
7
8
|
}
|
|
8
|
-
export declare const HtmlCodeViewer: ({ value, onChange, className, readOnly }: HtmlCodeViewerProps) => React.JSX.Element;
|
|
9
|
+
export declare const HtmlCodeViewer: ({ value, onChange, className, contentHeight, readOnly }: HtmlCodeViewerProps) => React.JSX.Element;
|
|
9
10
|
export {};
|
|
10
11
|
//# sourceMappingURL=html-code-viewer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"html-code-viewer.d.ts","sourceRoot":"","sources":["../../../../src/tiptap/components/html-code-viewer.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"html-code-viewer.d.ts","sourceRoot":"","sources":["../../../../src/tiptap/components/html-code-viewer.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAkD,MAAM,OAAO,CAAC;AAKvE,UAAU,mBAAmB;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,cAAc,GAAI,yDAM5B,mBAAmB,sBA2KrB,CAAC"}
|
|
@@ -1,38 +1,78 @@
|
|
|
1
|
-
import { useToken } from '@akinon/ui-theme';
|
|
1
|
+
import { getSafeCustomTokens, useToken } from '@akinon/ui-theme';
|
|
2
2
|
import { useStyleRegister } from '@ant-design/cssinjs';
|
|
3
3
|
import { ConfigProvider } from 'antd';
|
|
4
|
-
import React, { useRef } from 'react';
|
|
5
|
-
import {
|
|
6
|
-
import { highlightHtml } from '../utils';
|
|
7
|
-
export const HtmlCodeViewer = ({ value, onChange, className, readOnly = false }) => {
|
|
4
|
+
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
|
|
5
|
+
import { EDITOR_CONTENT_HEIGHT } from '../constants';
|
|
6
|
+
import { formatHtmlWithPrettier, highlightHtml } from '../utils';
|
|
7
|
+
export const HtmlCodeViewer = ({ value, onChange, className, contentHeight = EDITOR_CONTENT_HEIGHT, readOnly = false }) => {
|
|
8
8
|
const { getPrefixCls, theme } = React.useContext(ConfigProvider.ConfigContext);
|
|
9
9
|
const { token, hashId } = useToken();
|
|
10
10
|
const baseCls = getPrefixCls('html-code-viewer');
|
|
11
11
|
const preRef = useRef(null);
|
|
12
12
|
const colors = (theme === null || theme === void 0 ? void 0 : theme.colors) || {};
|
|
13
|
-
const handleScroll = (e) => {
|
|
13
|
+
const handleScroll = useCallback((e) => {
|
|
14
14
|
if (preRef.current) {
|
|
15
15
|
preRef.current.scrollTop = e.currentTarget.scrollTop;
|
|
16
16
|
preRef.current.scrollLeft = e.currentTarget.scrollLeft;
|
|
17
17
|
}
|
|
18
|
-
};
|
|
18
|
+
}, []);
|
|
19
|
+
const handleChange = useCallback((e) => {
|
|
20
|
+
onChange(e.target.value);
|
|
21
|
+
}, [onChange]);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
{
|
|
24
|
+
/*
|
|
25
|
+
Auto-format on mount (switching to source mode).
|
|
26
|
+
The isMounted check is necessary because formatHtmlWithPrettier is async.
|
|
27
|
+
If the component unmounts before format completes, we must not call onChange
|
|
28
|
+
to avoid "state update on unmounted component" errors.
|
|
29
|
+
*/
|
|
30
|
+
}
|
|
31
|
+
let isMounted = true;
|
|
32
|
+
const formatOnMount = async () => {
|
|
33
|
+
if (value && !readOnly) {
|
|
34
|
+
const formatted = await formatHtmlWithPrettier(value);
|
|
35
|
+
if (isMounted && formatted !== value) {
|
|
36
|
+
onChange(formatted);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
formatOnMount();
|
|
41
|
+
return () => {
|
|
42
|
+
isMounted = false;
|
|
43
|
+
};
|
|
44
|
+
}, []);
|
|
45
|
+
const handlePaste = useCallback(async (e) => {
|
|
46
|
+
if (readOnly)
|
|
47
|
+
return;
|
|
48
|
+
e.preventDefault();
|
|
49
|
+
const pastedText = e.clipboardData.getData('text/plain');
|
|
50
|
+
if (!pastedText)
|
|
51
|
+
return;
|
|
52
|
+
const textarea = e.currentTarget;
|
|
53
|
+
const start = textarea.selectionStart;
|
|
54
|
+
const end = textarea.selectionEnd;
|
|
55
|
+
const newValue = value.substring(0, start) + pastedText + value.substring(end);
|
|
56
|
+
const formatted = await formatHtmlWithPrettier(newValue);
|
|
57
|
+
onChange(formatted);
|
|
58
|
+
}, [readOnly, value, onChange]);
|
|
19
59
|
const useStyle = useStyleRegister({
|
|
20
60
|
token: token,
|
|
21
|
-
path: ['HtmlCodeViewer'],
|
|
61
|
+
path: ['HtmlCodeViewer', String(contentHeight)],
|
|
22
62
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
23
63
|
theme: theme
|
|
24
64
|
}, () => {
|
|
25
65
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
26
66
|
const prefixCls = `:where(.${hashId}).${baseCls}`;
|
|
67
|
+
const customTokens = getSafeCustomTokens(theme);
|
|
27
68
|
return {
|
|
28
69
|
[prefixCls]: {
|
|
29
70
|
position: 'relative',
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
borderRadius: '5px',
|
|
71
|
+
minHeight: `${contentHeight}px`,
|
|
72
|
+
height: `${contentHeight}px`,
|
|
73
|
+
border: `${customTokens.border.borderWidthThick} ${customTokens.border.borderSolid} ${(_a = colors.ebonyClay) === null || _a === void 0 ? void 0 : _a['550']}`,
|
|
74
|
+
borderBottomLeftRadius: '5px',
|
|
75
|
+
borderBottomRightRadius: '5px',
|
|
36
76
|
backgroundColor: (_b = colors.neutral) === null || _b === void 0 ? void 0 : _b['50'],
|
|
37
77
|
overflow: 'hidden',
|
|
38
78
|
'& textarea, & pre': {
|
|
@@ -68,29 +108,29 @@ export const HtmlCodeViewer = ({ value, onChange, className, readOnly = false })
|
|
|
68
108
|
color: (_d = colors.neutral) === null || _d === void 0 ? void 0 : _d['1000']
|
|
69
109
|
},
|
|
70
110
|
'.html-tag': {
|
|
71
|
-
color: (_e = colors.
|
|
111
|
+
color: (_e = colors.red) === null || _e === void 0 ? void 0 : _e['825']
|
|
72
112
|
},
|
|
73
113
|
'.html-attr': {
|
|
74
|
-
color: (_f = colors.
|
|
114
|
+
color: (_f = colors.red) === null || _f === void 0 ? void 0 : _f['999']
|
|
75
115
|
},
|
|
76
116
|
'.html-value': {
|
|
77
|
-
color: (_g = colors.
|
|
117
|
+
color: (_g = colors.blue) === null || _g === void 0 ? void 0 : _g['999']
|
|
78
118
|
},
|
|
79
119
|
'.html-comment': {
|
|
80
|
-
color: (_h = colors.
|
|
120
|
+
color: (_h = colors.green) === null || _h === void 0 ? void 0 : _h['825'],
|
|
81
121
|
fontStyle: 'italic'
|
|
82
122
|
},
|
|
83
123
|
'.html-doctype': {
|
|
84
|
-
color: (_j = colors.
|
|
124
|
+
color: (_j = colors.red) === null || _j === void 0 ? void 0 : _j['825']
|
|
85
125
|
},
|
|
86
126
|
'.html-string': {
|
|
87
|
-
color: (_k = colors.
|
|
127
|
+
color: (_k = colors.red) === null || _k === void 0 ? void 0 : _k['815']
|
|
88
128
|
}
|
|
89
129
|
}
|
|
90
130
|
};
|
|
91
131
|
});
|
|
92
|
-
const highlightedHtml = highlightHtml(value) + (value.endsWith('\n') ? '<br>' : '');
|
|
132
|
+
const highlightedHtml = useMemo(() => highlightHtml(value) + (value.endsWith('\n') ? '<br>' : ''), [value]);
|
|
93
133
|
return useStyle(React.createElement("div", { className: `${baseCls} ${hashId} ${className || ''}` },
|
|
94
|
-
React.createElement("textarea", { value: value, onChange:
|
|
134
|
+
React.createElement("textarea", { value: value, onChange: handleChange, onPaste: handlePaste, onScroll: handleScroll, readOnly: readOnly, spellCheck: false, autoCapitalize: "off", autoComplete: "off", autoCorrect: "off" }),
|
|
95
135
|
React.createElement("pre", { ref: preRef, "aria-hidden": "true", dangerouslySetInnerHTML: { __html: highlightedHtml } })));
|
|
96
136
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-upload-placeholder.d.ts","sourceRoot":"","sources":["../../../../src/tiptap/components/image-upload-placeholder.tsx"],"names":[],"mappings":"AAYA,OAAO,EAAE,aAAa,EAAmB,MAAM,eAAe,CAAC;AAE/D,OAAO,KAAK,MAAM,OAAO,CAAC;AA8B1B,eAAO,MAAM,sBAAsB,GAAI,0BAIpC,aAAa,
|
|
1
|
+
{"version":3,"file":"image-upload-placeholder.d.ts","sourceRoot":"","sources":["../../../../src/tiptap/components/image-upload-placeholder.tsx"],"names":[],"mappings":"AAYA,OAAO,EAAE,aAAa,EAAmB,MAAM,eAAe,CAAC;AAE/D,OAAO,KAAK,MAAM,OAAO,CAAC;AA8B1B,eAAO,MAAM,sBAAsB,GAAI,0BAIpC,aAAa,sBAiGf,CAAC"}
|
|
@@ -48,7 +48,7 @@ export const ImageUploadPlaceholder = ({ editor, node, getPos }) => {
|
|
|
48
48
|
borderRadius: '8px',
|
|
49
49
|
textAlign: 'center',
|
|
50
50
|
width: '50%',
|
|
51
|
-
backgroundColor: (_b = colors
|
|
51
|
+
backgroundColor: (_b = colors.neutral) === null || _b === void 0 ? void 0 : _b['50-05'],
|
|
52
52
|
['.ant-upload-wrapper .ant-upload-drag']: {
|
|
53
53
|
background: 'transparent',
|
|
54
54
|
border: 'none',
|
|
@@ -68,6 +68,9 @@ export const ImageUploadPlaceholder = ({ editor, node, getPos }) => {
|
|
|
68
68
|
color: (_e = colors.gray) === null || _e === void 0 ? void 0 : _e['500'],
|
|
69
69
|
fontSize: '2rem'
|
|
70
70
|
}
|
|
71
|
+
},
|
|
72
|
+
[`${prefixCls}-content`]: {
|
|
73
|
+
pointerEvents: 'none'
|
|
71
74
|
}
|
|
72
75
|
};
|
|
73
76
|
});
|
|
@@ -86,7 +89,7 @@ export const ImageUploadPlaceholder = ({ editor, node, getPos }) => {
|
|
|
86
89
|
return useStyle(React.createElement(NodeViewWrapper, { className: `${baseCls}-wrapper ${hashId}` },
|
|
87
90
|
React.createElement("div", { className: `${baseCls} ${hashId}` },
|
|
88
91
|
React.createElement(Upload.Dragger, { name: "file", multiple: false, showUploadList: false, beforeUpload: handleImageUpload },
|
|
89
|
-
React.createElement("div", {
|
|
92
|
+
React.createElement("div", { className: `${baseCls}-content ${hashId}` },
|
|
90
93
|
React.createElement("p", { className: "ant-upload-drag-icon" },
|
|
91
94
|
React.createElement(Button, { type: "icon", icon: "add_picture", size: "small" })),
|
|
92
95
|
React.createElement("p", { className: "ant-upload-text" }, i18n.t('editor.image_upload.click_to_upload')),
|