@blocklet/editor 1.6.198 → 1.6.200

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,3 +1,3 @@
1
1
  import { LexicalEditor } from 'lexical';
2
- import type { TranslationOptions, TranslateSelectionOperations } from './types';
3
- export declare const translateSelection: (editor: LexicalEditor, options: TranslationOptions) => Promise<TranslateSelectionOperations | null>;
2
+ import type { TranslationOptions, TranslationResult } from './types';
3
+ export declare const translateSelection: (editor: LexicalEditor, options: TranslationOptions) => Promise<TranslationResult | null>;
@@ -1,3 +1,3 @@
1
1
  import { type LexicalEditor } from 'lexical';
2
- import type { TranslationOptions, TranslateSelectionOperations } from './types';
3
- export declare const translateFullContent: (editor: LexicalEditor, options: TranslationOptions) => Promise<TranslateSelectionOperations | null>;
2
+ import type { TranslationOptions, TranslationResult } from './types';
3
+ export declare const translateFullContent: (editor: LexicalEditor, options: TranslationOptions) => Promise<TranslationResult | null>;
@@ -12,8 +12,16 @@ export const translateFullContent = async (editor, options) => {
12
12
  sourceTextsWithPlaceholder[key] = processPlaceholders(text);
13
13
  });
14
14
  const targetTexts = {};
15
- await translateAPI({ texts: sourceTextsWithPlaceholder, sourceLanguage, targetLanguage }, ({ data, progress }) => {
16
- targetTexts[data.key] = restorePlaceholders(sourceTexts[data.key], data.text);
15
+ const errorsMap = {};
16
+ await translateAPI({ texts: sourceTextsWithPlaceholder, sourceLanguage, targetLanguage }, ({ data, progress, error }) => {
17
+ const sourceText = sourceTexts[data.key];
18
+ if (error) {
19
+ targetTexts[data.key] = sourceText;
20
+ errorsMap[data.key] = error;
21
+ }
22
+ else {
23
+ targetTexts[data.key] = restorePlaceholders(sourceText, data.text);
24
+ }
17
25
  if (options.onProgress && progress) {
18
26
  options.onProgress(progress);
19
27
  }
@@ -28,8 +36,13 @@ export const translateFullContent = async (editor, options) => {
28
36
  };
29
37
  })
30
38
  .filter((x) => !!x.text);
39
+ const errors = translationBlocks
40
+ .filter((x) => !!errorsMap[x.key])
41
+ .map((item) => ({ ...item, error: errorsMap[item.key] }));
31
42
  // eslint-disable-next-line no-console
32
43
  console.log('translations: ', translations);
44
+ // eslint-disable-next-line no-console
45
+ console.log('errors: ', errors);
33
46
  // 默认自动替换
34
47
  const autoReplace = options.autoReplace !== false;
35
48
  if (autoReplace && !signal?.aborted) {
@@ -39,6 +52,7 @@ export const translateFullContent = async (editor, options) => {
39
52
  }
40
53
  return {
41
54
  translations,
55
+ errors,
42
56
  preview: () => {
43
57
  return editor.getEditorState().read(() => $preview(translations));
44
58
  },
@@ -20,9 +20,10 @@ export interface TranslatePayload {
20
20
  [key: string]: string;
21
21
  };
22
22
  }
23
- export type TranslateAPI = (payload: TranslatePayload, onData: ({ data, progress }: {
23
+ export type TranslateAPI = (payload: TranslatePayload, onData: ({ data, progress, error }: {
24
24
  data: TranslationBlock;
25
25
  progress?: number;
26
+ error?: string;
26
27
  }) => void) => Promise<void>;
27
28
  export interface TranslationOptions {
28
29
  sourceLanguage?: string;
@@ -33,8 +34,16 @@ export interface TranslationOptions {
33
34
  autoReplace?: boolean;
34
35
  }
35
36
  export interface TranslateSelectionOperations {
36
- translations: TranslationBlock[];
37
37
  preview: () => string;
38
38
  replace: (editor?: LexicalEditor) => void;
39
39
  insertBelow: () => void;
40
40
  }
41
+ export interface TranslationError {
42
+ key: string;
43
+ text: string;
44
+ error: string;
45
+ }
46
+ export interface TranslationResult extends TranslateSelectionOperations {
47
+ translations: TranslationBlock[];
48
+ errors?: TranslationError[];
49
+ }
@@ -4,8 +4,9 @@ import { $isListNode, $isListItemNode } from '@lexical/list';
4
4
  import { $dfs, $findMatchingParent } from '@lexical/utils';
5
5
  import { fetchEventSource } from '@microsoft/fetch-event-source';
6
6
  import { $createLinkNode, $isLinkNode } from '@lexical/link';
7
- import { blockletExists, getBlockletMountPointInfo } from '../utils';
7
+ import { blockletExists, getBlockletMountPointInfo, isValidUrl } from '../utils';
8
8
  import { $getDepth } from '../../lexical-utils';
9
+ const PLACEHOLDER = '[[PLACEHOLDER]]';
9
10
  export const defaultTranslateAPI = async ({ texts, sourceLanguage, targetLanguage }, onData) => {
10
11
  if (!blockletExists('did-comments')) {
11
12
  throw new Error('Discuss Kit component must be installed.');
@@ -23,11 +24,12 @@ export const defaultTranslateAPI = async ({ texts, sourceLanguage, targetLanguag
23
24
  // @see: https://github.com/Azure/fetch-event-source/issues/36
24
25
  openWhenHidden: true,
25
26
  onmessage: (ev) => {
26
- const parsed = JSON.parse(ev.data);
27
- if (ev.event === 'error') {
28
- throw new Error(parsed.message);
29
- }
30
- const data = { data: parsed, progress: Number((++done / total).toFixed(2)) * 100 };
27
+ const { error, ...parsed } = JSON.parse(ev.data);
28
+ const data = {
29
+ data: parsed,
30
+ progress: Number((++done / total).toFixed(2)) * 100,
31
+ error,
32
+ };
31
33
  // eslint-disable-next-line no-console
32
34
  console.log('onmessage: ', ev, data);
33
35
  onData(data);
@@ -158,7 +160,14 @@ export const $extractTranslationBlocks = (translationNodes) => {
158
160
  const text = $extractTextContentFromTranslationNode(node);
159
161
  return { key: node.getKey(), text };
160
162
  })
161
- .filter((item) => !!item.text);
163
+ .filter((item) => {
164
+ const trim = item.text?.trim();
165
+ // 如果为空或 url, 则不翻译
166
+ if (!trim || isValidUrl(trim)) {
167
+ return false;
168
+ }
169
+ return true;
170
+ });
162
171
  };
163
172
  /**
164
173
  * 处理带有 `###key###` 的文本, 将普通文本转成 TextNode, 将 `###key###` 替换成 key 对应的 Node
@@ -366,14 +375,14 @@ export const $extractTranslationBlocksFromSelection = (selection) => {
366
375
  // console.log({ firstTranslationBlock, blocks, lastTranslationBlock });
367
376
  return [firstTranslationBlock, ...blocks, lastTranslationBlock].filter((item) => !!item?.text);
368
377
  };
369
- export const processPlaceholders = (text, placeholder = '@@@@@') => {
378
+ export const processPlaceholders = (text, placeholder = PLACEHOLDER) => {
370
379
  const matches = text.match(/###\d+###/g);
371
380
  if (matches) {
372
381
  return text.replaceAll(/###\d+###/g, placeholder);
373
382
  }
374
383
  return text;
375
384
  };
376
- export const restorePlaceholders = (original, replacedText, placeholder = '@@@@@') => {
385
+ export const restorePlaceholders = (original, replacedText, placeholder = PLACEHOLDER) => {
377
386
  const matches = original.match(/###\d+###/g);
378
387
  if (matches) {
379
388
  return matches.reduce((acc, cur) => {
@@ -1,6 +1,7 @@
1
1
  import { LinkNode } from '@lexical/link';
2
2
  import { type LexicalEditor } from 'lexical';
3
3
  export declare function joinUrl(...paths: string[]): string;
4
+ export declare function isValidUrl(url: string): boolean;
4
5
  export declare const safeParseJSON: (json: string, defaultValue?: any) => any;
5
6
  export declare const getBlockletMountPointInfo: (name: string) => any;
6
7
  export declare const blockletExists: (name: string) => boolean;
package/lib/ext/utils.js CHANGED
@@ -7,6 +7,16 @@ function dedupeSlashes(path) {
7
7
  export function joinUrl(...paths) {
8
8
  return dedupeSlashes(paths.join('/'));
9
9
  }
10
+ export function isValidUrl(url) {
11
+ try {
12
+ // eslint-disable-next-line no-new
13
+ new URL(url);
14
+ }
15
+ catch {
16
+ return false;
17
+ }
18
+ return true;
19
+ }
10
20
  export const safeParseJSON = (json, defaultValue = null) => {
11
21
  try {
12
22
  return JSON.parse(json);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocklet/editor",
3
- "version": "1.6.198",
3
+ "version": "1.6.200",
4
4
  "main": "lib/index.js",
5
5
  "scripts": {
6
6
  "dev": "npm run storybook",
@@ -39,7 +39,7 @@
39
39
  "dependencies": {
40
40
  "@arcblock/ux": "^2.9.63",
41
41
  "@blocklet/embed": "^0.1.11",
42
- "@blocklet/pdf": "1.6.198",
42
+ "@blocklet/pdf": "1.6.200",
43
43
  "@excalidraw/excalidraw": "^0.14.2",
44
44
  "@iconify/iconify": "^3.0.1",
45
45
  "@lexical/clipboard": "0.13.1",
@@ -108,5 +108,5 @@
108
108
  "react": "*",
109
109
  "react-dom": "*"
110
110
  },
111
- "gitHead": "9dd144eeaf7f42dfeb617e9260565114f220e206"
111
+ "gitHead": "9a1304683bb3a7775d995c6cb5e5ffcee39be438"
112
112
  }