@quadrats/common 1.0.0 → 1.1.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.
@@ -1 +1,2 @@
1
1
  export declare const ALIGN_TYPE = "align";
2
+ export declare const ALIGNABLE_TYPES: string[];
@@ -1,3 +1,7 @@
1
+ import { HEADING_TYPE } from '@quadrats/common/heading';
2
+ import { PARAGRAPH_TYPE } from '@quadrats/core';
3
+
1
4
  const ALIGN_TYPE = 'align';
5
+ const ALIGNABLE_TYPES = [PARAGRAPH_TYPE, HEADING_TYPE];
2
6
 
3
- export { ALIGN_TYPE };
7
+ export { ALIGNABLE_TYPES, ALIGN_TYPE };
@@ -1,8 +1,6 @@
1
- import { Transforms, Element, PARAGRAPH_TYPE, Editor } from '@quadrats/core';
2
- import { HEADING_TYPE } from '@quadrats/common/heading';
3
- import { ALIGN_TYPE } from './constants.js';
1
+ import { Transforms, Element, Editor } from '@quadrats/core';
2
+ import { ALIGN_TYPE, ALIGNABLE_TYPES } from './constants.js';
4
3
 
5
- const ALIGNABLE_TYPES = [PARAGRAPH_TYPE, HEADING_TYPE];
6
4
  function createAlign() {
7
5
  const type = ALIGN_TYPE;
8
6
  return {
@@ -1,11 +1,11 @@
1
1
  'use strict';
2
2
 
3
- var core = require('@quadrats/core');
4
3
  var heading = require('@quadrats/common/heading');
4
+ var core = require('@quadrats/core');
5
5
 
6
6
  const ALIGN_TYPE = 'align';
7
-
8
7
  const ALIGNABLE_TYPES = [core.PARAGRAPH_TYPE, heading.HEADING_TYPE];
8
+
9
9
  function createAlign() {
10
10
  const type = ALIGN_TYPE;
11
11
  return {
@@ -41,5 +41,6 @@ function createAlign() {
41
41
  };
42
42
  }
43
43
 
44
+ exports.ALIGNABLE_TYPES = ALIGNABLE_TYPES;
44
45
  exports.ALIGN_TYPE = ALIGN_TYPE;
45
46
  exports.createAlign = createAlign;
package/align/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export { ALIGN_TYPE } from './constants.js';
1
+ export { ALIGNABLE_TYPES, ALIGN_TYPE } from './constants.js';
2
2
  export { createAlign } from './createAlign.js';
@@ -1,5 +1,6 @@
1
- import { isNodesTypeIn, wrapNodesWithUnhangRange, unwrapNodesByTypes } from '@quadrats/core';
1
+ import { isNodesTypeIn, Editor, wrapNodesWithUnhangRange, unwrapNodesByTypes } from '@quadrats/core';
2
2
  import { BLOCKQUOTE_TYPE } from './constants.js';
3
+ import { TABLE_CELL_TYPE } from '@quadrats/common/table';
3
4
 
4
5
  function createBlockquote({ type = BLOCKQUOTE_TYPE } = {}) {
5
6
  const unwrapBlockquote = (editor) => {
@@ -12,21 +13,37 @@ function createBlockquote({ type = BLOCKQUOTE_TYPE } = {}) {
12
13
  };
13
14
  wrapNodesWithUnhangRange(editor, element, { split: true });
14
15
  };
15
- const isSelectionInBlockquote = editor => (isNodesTypeIn(editor, [type], { mode: 'highest' }));
16
+ const isSelectionInBlockquote = (editor) => isNodesTypeIn(editor, [type], { mode: 'highest' });
16
17
  return {
17
18
  type,
18
19
  unwrapBlockquote,
19
20
  wrapBlockquote,
20
21
  isSelectionInBlockquote,
21
22
  toggleBlockquote: (editor) => {
22
- const actived = isSelectionInBlockquote(editor);
23
- if (editor.selection) {
24
- if (actived) {
25
- unwrapBlockquote(editor);
26
- }
27
- else {
28
- wrapBlockquote(editor);
29
- }
23
+ if (!editor.selection) {
24
+ return;
25
+ }
26
+ // 檢查是否在不合法範圍中,如果是則不執行 toggle
27
+ try {
28
+ const invalidEntry = Editor.above(editor, {
29
+ at: editor.selection,
30
+ match: (n) => {
31
+ const element = n;
32
+ return element.type === TABLE_CELL_TYPE;
33
+ },
34
+ });
35
+ if (invalidEntry)
36
+ return;
37
+ }
38
+ catch (error) {
39
+ return;
40
+ }
41
+ const active = isSelectionInBlockquote(editor);
42
+ if (active) {
43
+ unwrapBlockquote(editor);
44
+ }
45
+ else {
46
+ wrapBlockquote(editor);
30
47
  }
31
48
  },
32
49
  with(editor) {
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var core = require('@quadrats/core');
4
+ var table = require('@quadrats/common/table');
4
5
 
5
6
  const BLOCKQUOTE_TYPE = 'blockquote';
6
7
 
@@ -15,21 +16,37 @@ function createBlockquote({ type = BLOCKQUOTE_TYPE } = {}) {
15
16
  };
16
17
  core.wrapNodesWithUnhangRange(editor, element, { split: true });
17
18
  };
18
- const isSelectionInBlockquote = editor => (core.isNodesTypeIn(editor, [type], { mode: 'highest' }));
19
+ const isSelectionInBlockquote = (editor) => core.isNodesTypeIn(editor, [type], { mode: 'highest' });
19
20
  return {
20
21
  type,
21
22
  unwrapBlockquote,
22
23
  wrapBlockquote,
23
24
  isSelectionInBlockquote,
24
25
  toggleBlockquote: (editor) => {
25
- const actived = isSelectionInBlockquote(editor);
26
- if (editor.selection) {
27
- if (actived) {
28
- unwrapBlockquote(editor);
29
- }
30
- else {
31
- wrapBlockquote(editor);
32
- }
26
+ if (!editor.selection) {
27
+ return;
28
+ }
29
+ // 檢查是否在不合法範圍中,如果是則不執行 toggle
30
+ try {
31
+ const invalidEntry = core.Editor.above(editor, {
32
+ at: editor.selection,
33
+ match: (n) => {
34
+ const element = n;
35
+ return element.type === table.TABLE_CELL_TYPE;
36
+ },
37
+ });
38
+ if (invalidEntry)
39
+ return;
40
+ }
41
+ catch (error) {
42
+ return;
43
+ }
44
+ const active = isSelectionInBlockquote(editor);
45
+ if (active) {
46
+ unwrapBlockquote(editor);
47
+ }
48
+ else {
49
+ wrapBlockquote(editor);
33
50
  }
34
51
  },
35
52
  with(editor) {
@@ -1,11 +1,12 @@
1
1
  import { __awaiter } from './_virtual/_tslib.js';
2
2
  import { readFileAsDataURL } from '@quadrats/utils';
3
- import { isAboveBlockEmpty, Transforms, createParagraphElement, Element, Editor, HistoryEditor } from '@quadrats/core';
3
+ import { Editor, isAboveBlockEmpty, Transforms, createParagraphElement, Element, HistoryEditor } from '@quadrats/core';
4
4
  import { FILE_UPLOADER_TYPE, FILE_UPLOADER_PLACEHOLDER_TYPE } from './constants.js';
5
5
  import { getFilesFromInput } from './getFilesFromInput.js';
6
+ import { TABLE_CELL_TYPE } from '@quadrats/common/table';
6
7
 
7
- const createFileUploaderElementByType = type => (editor, file, options) => __awaiter(void 0, void 0, void 0, function* () {
8
- const { createElement, getBody, getHeaders, getUrl, uploader, } = options;
8
+ const createFileUploaderElementByType = (type) => (editor, file, options) => __awaiter(void 0, void 0, void 0, function* () {
9
+ const { createElement, getBody, getHeaders, getUrl, uploader } = options;
9
10
  const [mime] = file.type.split('/');
10
11
  const createByMime = createElement[mime];
11
12
  if (!createByMime) {
@@ -54,16 +55,32 @@ const createFileUploaderElementByType = type => (editor, file, options) => __awa
54
55
  return fileUploaderElement;
55
56
  });
56
57
  function insertFileUploaderElement(editor, fileUploaderElement) {
57
- var _a, _b, _c;
58
+ var _a, _b;
58
59
  if (fileUploaderElement) {
60
+ // 驗證當前 selection 是否仍然有效
61
+ if (!editor.selection) {
62
+ return;
63
+ }
64
+ try {
65
+ // 嘗試取得當前選取位置的節點,確保路徑仍然有效
66
+ const node = Editor.node(editor, editor.selection);
67
+ if (!node) {
68
+ return;
69
+ }
70
+ }
71
+ catch (error) {
72
+ // 如果路徑無效(例如 placeholder 已被移除),靜默失敗
73
+ console.warn('Cannot insert file uploader element: invalid selection path', error);
74
+ return;
75
+ }
59
76
  // Clear empty node
60
77
  if (isAboveBlockEmpty(editor)) {
61
78
  Transforms.removeNodes(editor, {
62
- at: (_a = editor.selection) === null || _a === void 0 ? void 0 : _a.anchor,
79
+ at: editor.selection.anchor,
63
80
  });
64
81
  }
65
82
  Transforms.insertNodes(editor, [fileUploaderElement, createParagraphElement()], {
66
- at: ((_b = editor.selection) === null || _b === void 0 ? void 0 : _b.anchor.path.length) ? [((_c = editor.selection) === null || _c === void 0 ? void 0 : _c.anchor.path[0]) + 1] : undefined,
83
+ at: ((_a = editor.selection) === null || _a === void 0 ? void 0 : _a.anchor.path.length) ? [((_b = editor.selection) === null || _b === void 0 ? void 0 : _b.anchor.path[0]) + 1] : undefined,
67
84
  });
68
85
  Transforms.move(editor);
69
86
  }
@@ -73,10 +90,24 @@ function createFileUploader(options = {}) {
73
90
  const createFileUploaderElement = createFileUploaderElementByType(type);
74
91
  const removeUploaderPlaceholder = (editor) => {
75
92
  Transforms.removeNodes(editor, {
76
- match: node => Element.isElement(node) && node.type === FILE_UPLOADER_PLACEHOLDER_TYPE,
93
+ match: (node) => Element.isElement(node) && node.type === FILE_UPLOADER_PLACEHOLDER_TYPE,
77
94
  });
78
95
  };
79
96
  const upload = (editor, options) => __awaiter(this, void 0, void 0, function* () {
97
+ // 檢查是否在不允許的元件之中,如果是則不執行上傳
98
+ if (editor.selection) {
99
+ try {
100
+ const invalidEntry = Editor.above(editor, {
101
+ at: editor.selection,
102
+ match: (n) => Element.isElement(n) && n.type === TABLE_CELL_TYPE,
103
+ });
104
+ if (invalidEntry)
105
+ return;
106
+ }
107
+ catch (error) {
108
+ return;
109
+ }
110
+ }
80
111
  const { accept, multiple } = options;
81
112
  const files = yield getFilesFromInput({ accept, multiple });
82
113
  if (!files) {
@@ -92,6 +123,20 @@ function createFileUploader(options = {}) {
92
123
  }), Promise.resolve());
93
124
  });
94
125
  const insertUploaderPlaceholder = (editor) => {
126
+ // 檢查是否在不允許的元件之中,如果是則不插入 placeholder
127
+ if (editor.selection) {
128
+ try {
129
+ const invalidEntry = Editor.above(editor, {
130
+ at: editor.selection,
131
+ match: (n) => Element.isElement(n) && n.type === TABLE_CELL_TYPE,
132
+ });
133
+ if (invalidEntry)
134
+ return;
135
+ }
136
+ catch (error) {
137
+ return;
138
+ }
139
+ }
95
140
  const uploaderPlaceholderElement = {
96
141
  type: FILE_UPLOADER_PLACEHOLDER_TYPE,
97
142
  children: [{ text: '' }],
@@ -2,6 +2,7 @@
2
2
 
3
3
  var utils = require('@quadrats/utils');
4
4
  var core = require('@quadrats/core');
5
+ var table = require('@quadrats/common/table');
5
6
 
6
7
  const FILE_UPLOADER_TYPE = 'file_uploader';
7
8
  const FILE_UPLOADER_PLACEHOLDER_TYPE = 'file_uploader_placeholder';
@@ -67,8 +68,8 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
67
68
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
68
69
  };
69
70
 
70
- const createFileUploaderElementByType = type => (editor, file, options) => __awaiter(void 0, void 0, void 0, function* () {
71
- const { createElement, getBody, getHeaders, getUrl, uploader, } = options;
71
+ const createFileUploaderElementByType = (type) => (editor, file, options) => __awaiter(void 0, void 0, void 0, function* () {
72
+ const { createElement, getBody, getHeaders, getUrl, uploader } = options;
72
73
  const [mime] = file.type.split('/');
73
74
  const createByMime = createElement[mime];
74
75
  if (!createByMime) {
@@ -117,16 +118,32 @@ const createFileUploaderElementByType = type => (editor, file, options) => __awa
117
118
  return fileUploaderElement;
118
119
  });
119
120
  function insertFileUploaderElement(editor, fileUploaderElement) {
120
- var _a, _b, _c;
121
+ var _a, _b;
121
122
  if (fileUploaderElement) {
123
+ // 驗證當前 selection 是否仍然有效
124
+ if (!editor.selection) {
125
+ return;
126
+ }
127
+ try {
128
+ // 嘗試取得當前選取位置的節點,確保路徑仍然有效
129
+ const node = core.Editor.node(editor, editor.selection);
130
+ if (!node) {
131
+ return;
132
+ }
133
+ }
134
+ catch (error) {
135
+ // 如果路徑無效(例如 placeholder 已被移除),靜默失敗
136
+ console.warn('Cannot insert file uploader element: invalid selection path', error);
137
+ return;
138
+ }
122
139
  // Clear empty node
123
140
  if (core.isAboveBlockEmpty(editor)) {
124
141
  core.Transforms.removeNodes(editor, {
125
- at: (_a = editor.selection) === null || _a === void 0 ? void 0 : _a.anchor,
142
+ at: editor.selection.anchor,
126
143
  });
127
144
  }
128
145
  core.Transforms.insertNodes(editor, [fileUploaderElement, core.createParagraphElement()], {
129
- at: ((_b = editor.selection) === null || _b === void 0 ? void 0 : _b.anchor.path.length) ? [((_c = editor.selection) === null || _c === void 0 ? void 0 : _c.anchor.path[0]) + 1] : undefined,
146
+ at: ((_a = editor.selection) === null || _a === void 0 ? void 0 : _a.anchor.path.length) ? [((_b = editor.selection) === null || _b === void 0 ? void 0 : _b.anchor.path[0]) + 1] : undefined,
130
147
  });
131
148
  core.Transforms.move(editor);
132
149
  }
@@ -136,10 +153,24 @@ function createFileUploader(options = {}) {
136
153
  const createFileUploaderElement = createFileUploaderElementByType(type);
137
154
  const removeUploaderPlaceholder = (editor) => {
138
155
  core.Transforms.removeNodes(editor, {
139
- match: node => core.Element.isElement(node) && node.type === FILE_UPLOADER_PLACEHOLDER_TYPE,
156
+ match: (node) => core.Element.isElement(node) && node.type === FILE_UPLOADER_PLACEHOLDER_TYPE,
140
157
  });
141
158
  };
142
159
  const upload = (editor, options) => __awaiter(this, void 0, void 0, function* () {
160
+ // 檢查是否在不允許的元件之中,如果是則不執行上傳
161
+ if (editor.selection) {
162
+ try {
163
+ const invalidEntry = core.Editor.above(editor, {
164
+ at: editor.selection,
165
+ match: (n) => core.Element.isElement(n) && n.type === table.TABLE_CELL_TYPE,
166
+ });
167
+ if (invalidEntry)
168
+ return;
169
+ }
170
+ catch (error) {
171
+ return;
172
+ }
173
+ }
143
174
  const { accept, multiple } = options;
144
175
  const files = yield getFilesFromInput({ accept, multiple });
145
176
  if (!files) {
@@ -155,6 +186,20 @@ function createFileUploader(options = {}) {
155
186
  }), Promise.resolve());
156
187
  });
157
188
  const insertUploaderPlaceholder = (editor) => {
189
+ // 檢查是否在不允許的元件之中,如果是則不插入 placeholder
190
+ if (editor.selection) {
191
+ try {
192
+ const invalidEntry = core.Editor.above(editor, {
193
+ at: editor.selection,
194
+ match: (n) => core.Element.isElement(n) && n.type === table.TABLE_CELL_TYPE,
195
+ });
196
+ if (invalidEntry)
197
+ return;
198
+ }
199
+ catch (error) {
200
+ return;
201
+ }
202
+ }
158
203
  const uploaderPlaceholderElement = {
159
204
  type: FILE_UPLOADER_PLACEHOLDER_TYPE,
160
205
  children: [{ text: '' }],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quadrats/common",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "description": "",
5
5
  "author": "Rytass",
6
6
  "homepage": "https://github.com/Quadrats/quadrats#readme",
@@ -18,7 +18,7 @@
18
18
  "url": "https://github.com/Quadrats/quadrats/issues"
19
19
  },
20
20
  "dependencies": {
21
- "@quadrats/core": "^1.0.0",
21
+ "@quadrats/core": "^1.1.0",
22
22
  "@quadrats/locales": "^1.0.0",
23
23
  "@quadrats/utils": "^1.0.0"
24
24
  }
@@ -0,0 +1,14 @@
1
+ import { TableTypes } from './typings';
2
+ export declare const TABLE_TYPE = "table";
3
+ export declare const TABLE_TITLE_TYPE = "table_title";
4
+ export declare const TABLE_MAIN_TYPE = "table_main";
5
+ export declare const TABLE_HEADER_TYPE = "table_header";
6
+ export declare const TABLE_BODY_TYPE = "table_body";
7
+ export declare const TABLE_ROW_TYPE = "table_row";
8
+ export declare const TABLE_CELL_TYPE = "table_cell";
9
+ export declare const TABLE_TYPES: TableTypes;
10
+ export declare const TABLE_DEFAULT_MAX_COLUMNS = 6;
11
+ export declare const TABLE_DEFAULT_MAX_ROWS = -1;
12
+ export declare const MAX_PINNED_COLUMNS_WIDTH_PERCENTAGE = 40;
13
+ export declare const MIN_COLUMN_WIDTH_PIXEL = 60;
14
+ export declare const MIN_COLUMN_WIDTH_PERCENTAGE = 5;
@@ -0,0 +1,25 @@
1
+ const TABLE_TYPE = 'table';
2
+ const TABLE_TITLE_TYPE = 'table_title';
3
+ const TABLE_MAIN_TYPE = 'table_main';
4
+ const TABLE_HEADER_TYPE = 'table_header';
5
+ const TABLE_BODY_TYPE = 'table_body';
6
+ const TABLE_ROW_TYPE = 'table_row';
7
+ const TABLE_CELL_TYPE = 'table_cell';
8
+ const TABLE_TYPES = {
9
+ table: TABLE_TYPE,
10
+ table_title: TABLE_TITLE_TYPE,
11
+ table_main: TABLE_MAIN_TYPE,
12
+ table_header: TABLE_HEADER_TYPE,
13
+ table_body: TABLE_BODY_TYPE,
14
+ table_row: TABLE_ROW_TYPE,
15
+ table_cell: TABLE_CELL_TYPE,
16
+ };
17
+ // Table limits
18
+ const TABLE_DEFAULT_MAX_COLUMNS = 6;
19
+ const TABLE_DEFAULT_MAX_ROWS = -1;
20
+ // 釘選欄位的最大總寬度百分比
21
+ const MAX_PINNED_COLUMNS_WIDTH_PERCENTAGE = 40;
22
+ const MIN_COLUMN_WIDTH_PIXEL = 60;
23
+ const MIN_COLUMN_WIDTH_PERCENTAGE = 5;
24
+
25
+ export { MAX_PINNED_COLUMNS_WIDTH_PERCENTAGE, MIN_COLUMN_WIDTH_PERCENTAGE, MIN_COLUMN_WIDTH_PIXEL, TABLE_BODY_TYPE, TABLE_CELL_TYPE, TABLE_DEFAULT_MAX_COLUMNS, TABLE_DEFAULT_MAX_ROWS, TABLE_HEADER_TYPE, TABLE_MAIN_TYPE, TABLE_ROW_TYPE, TABLE_TITLE_TYPE, TABLE_TYPE, TABLE_TYPES };
@@ -0,0 +1,6 @@
1
+ import { Editor } from '@quadrats/core';
2
+ import { Table, TableTypes } from './typings';
3
+ export interface CreateTableOptions {
4
+ types?: Partial<TableTypes>;
5
+ }
6
+ export declare function createTable(options?: CreateTableOptions): Table<Editor>;