@quadrats/common 0.7.7 → 1.1.0

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.
Files changed (88) hide show
  1. package/accordion/constants.d.ts +5 -0
  2. package/accordion/constants.js +10 -0
  3. package/accordion/createAccordion.d.ts +6 -0
  4. package/accordion/createAccordion.js +62 -0
  5. package/accordion/index.cjs.js +76 -0
  6. package/accordion/index.d.ts +3 -0
  7. package/accordion/index.js +2 -0
  8. package/accordion/package.json +7 -0
  9. package/accordion/typings.d.ts +18 -0
  10. package/align/constants.d.ts +2 -0
  11. package/align/constants.js +7 -0
  12. package/align/createAlign.d.ts +9 -0
  13. package/align/createAlign.js +39 -0
  14. package/align/index.cjs.js +46 -0
  15. package/align/index.d.ts +3 -0
  16. package/align/index.js +2 -0
  17. package/align/package.json +7 -0
  18. package/align/typings.d.ts +1 -0
  19. package/blockquote/createBlockquote.js +27 -10
  20. package/blockquote/index.cjs.js +26 -9
  21. package/card/constants.d.ts +6 -0
  22. package/card/constants.js +11 -0
  23. package/card/createCard.d.ts +15 -0
  24. package/card/createCard.js +147 -0
  25. package/card/getFilesFromInput.d.ts +4 -0
  26. package/card/index.cjs.js +163 -0
  27. package/card/index.d.ts +3 -0
  28. package/card/index.js +2 -0
  29. package/card/package.json +7 -0
  30. package/card/typings.d.ts +73 -0
  31. package/carousel/_virtual/_tslib.js +33 -0
  32. package/carousel/constants.d.ts +6 -0
  33. package/carousel/constants.js +11 -0
  34. package/carousel/createCarousel.d.ts +16 -0
  35. package/carousel/createCarousel.js +127 -0
  36. package/carousel/getFilesFromInput.d.ts +4 -0
  37. package/carousel/getFilesFromInput.js +30 -0
  38. package/carousel/index.cjs.js +202 -0
  39. package/carousel/index.d.ts +3 -0
  40. package/carousel/index.js +2 -0
  41. package/carousel/package.json +7 -0
  42. package/carousel/typings.d.ts +58 -0
  43. package/embed/constants.d.ts +1 -0
  44. package/embed/constants.js +2 -1
  45. package/embed/createEmbed.js +21 -4
  46. package/embed/index.cjs.js +26 -9
  47. package/embed/index.js +1 -1
  48. package/embed/serializeEmbedCode.d.ts +1 -1
  49. package/embed/serializeEmbedCode.js +5 -7
  50. package/embed/strategies/podcast-apple/index.cjs.js +1 -1
  51. package/embed/strategies/podcast-apple/index.js +1 -1
  52. package/embed/typings.d.ts +16 -1
  53. package/file-uploader/constants.d.ts +1 -0
  54. package/file-uploader/constants.js +2 -1
  55. package/file-uploader/createFileUploader.js +70 -7
  56. package/file-uploader/getFilesFromInput.js +3 -0
  57. package/file-uploader/index.cjs.js +73 -5
  58. package/file-uploader/index.js +1 -1
  59. package/file-uploader/typings.d.ts +8 -2
  60. package/heading/typings.d.ts +1 -0
  61. package/image/createImage.js +12 -11
  62. package/image/getImageFigureElementCommonProps.d.ts +2 -0
  63. package/image/getImageFigureElementCommonProps.js +28 -2
  64. package/image/index.cjs.js +40 -13
  65. package/image/typings.d.ts +2 -0
  66. package/list/createList.d.ts +1 -0
  67. package/list/createList.js +3 -0
  68. package/list/index.cjs.js +3 -0
  69. package/list/typings.d.ts +1 -0
  70. package/package.json +4 -4
  71. package/paragraph/createParagraph.d.ts +2 -0
  72. package/paragraph/createParagraph.js +24 -0
  73. package/paragraph/index.cjs.js +26 -0
  74. package/paragraph/index.d.ts +2 -0
  75. package/paragraph/index.js +1 -0
  76. package/paragraph/package.json +7 -0
  77. package/paragraph/typings.d.ts +9 -0
  78. package/table/constants.d.ts +14 -0
  79. package/table/constants.js +25 -0
  80. package/table/createTable.d.ts +6 -0
  81. package/table/createTable.js +429 -0
  82. package/table/index.cjs.js +714 -0
  83. package/table/index.d.ts +4 -0
  84. package/table/index.js +3 -0
  85. package/table/package.json +7 -0
  86. package/table/typings.d.ts +70 -0
  87. package/table/utils.d.ts +68 -0
  88. package/table/utils.js +243 -0
@@ -2,8 +2,10 @@
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';
8
+ const FILE_UPLOADER_PLACEHOLDER_TYPE = 'file_uploader_placeholder';
7
9
 
8
10
  function getFilesFromInput(options = {}) {
9
11
  const { accept, multiple } = options;
@@ -14,6 +16,9 @@ function getFilesFromInput(options = {}) {
14
16
  }
15
17
  inputEl.multiple = !!multiple;
16
18
  inputEl.type = 'file';
19
+ inputEl.addEventListener('cancel', () => {
20
+ resolve(undefined);
21
+ });
17
22
  inputEl.addEventListener('change', () => {
18
23
  const { files: fileList } = inputEl;
19
24
  if (!fileList || !fileList.length) {
@@ -63,8 +68,8 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
63
68
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
64
69
  };
65
70
 
66
- const createFileUploaderElementByType = type => (editor, file, options) => __awaiter(void 0, void 0, void 0, function* () {
67
- 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;
68
73
  const [mime] = file.type.split('/');
69
74
  const createByMime = createElement[mime];
70
75
  if (!createByMime) {
@@ -113,16 +118,32 @@ const createFileUploaderElementByType = type => (editor, file, options) => __awa
113
118
  return fileUploaderElement;
114
119
  });
115
120
  function insertFileUploaderElement(editor, fileUploaderElement) {
116
- var _a, _b, _c;
121
+ var _a, _b;
117
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
+ }
118
139
  // Clear empty node
119
140
  if (core.isAboveBlockEmpty(editor)) {
120
141
  core.Transforms.removeNodes(editor, {
121
- at: (_a = editor.selection) === null || _a === void 0 ? void 0 : _a.anchor,
142
+ at: editor.selection.anchor,
122
143
  });
123
144
  }
124
145
  core.Transforms.insertNodes(editor, [fileUploaderElement, core.createParagraphElement()], {
125
- 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,
126
147
  });
127
148
  core.Transforms.move(editor);
128
149
  }
@@ -130,12 +151,33 @@ function insertFileUploaderElement(editor, fileUploaderElement) {
130
151
  function createFileUploader(options = {}) {
131
152
  const { type = FILE_UPLOADER_TYPE } = options;
132
153
  const createFileUploaderElement = createFileUploaderElementByType(type);
154
+ const removeUploaderPlaceholder = (editor) => {
155
+ core.Transforms.removeNodes(editor, {
156
+ match: (node) => core.Element.isElement(node) && node.type === FILE_UPLOADER_PLACEHOLDER_TYPE,
157
+ });
158
+ };
133
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
+ }
134
174
  const { accept, multiple } = options;
135
175
  const files = yield getFilesFromInput({ accept, multiple });
136
176
  if (!files) {
177
+ removeUploaderPlaceholder(editor);
137
178
  return;
138
179
  }
180
+ removeUploaderPlaceholder(editor);
139
181
  files.reduce((prev, file) => __awaiter(this, void 0, void 0, function* () {
140
182
  yield prev;
141
183
  return createFileUploaderElement(editor, file, options).then((fileUploaderElement) => {
@@ -143,16 +185,42 @@ function createFileUploader(options = {}) {
143
185
  });
144
186
  }), Promise.resolve());
145
187
  });
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
+ }
203
+ const uploaderPlaceholderElement = {
204
+ type: FILE_UPLOADER_PLACEHOLDER_TYPE,
205
+ children: [{ text: '' }],
206
+ };
207
+ core.Editor.withoutNormalizing(editor, () => {
208
+ core.Transforms.insertNodes(editor, uploaderPlaceholderElement);
209
+ });
210
+ };
146
211
  return {
147
212
  type,
148
213
  createFileUploaderElement,
149
214
  upload,
215
+ insertUploaderPlaceholder,
216
+ removeUploaderPlaceholder,
150
217
  with(editor) {
151
218
  return editor;
152
219
  },
153
220
  };
154
221
  }
155
222
 
223
+ exports.FILE_UPLOADER_PLACEHOLDER_TYPE = FILE_UPLOADER_PLACEHOLDER_TYPE;
156
224
  exports.FILE_UPLOADER_TYPE = FILE_UPLOADER_TYPE;
157
225
  exports.createFileUploader = createFileUploader;
158
226
  exports.createFileUploaderElementByType = createFileUploaderElementByType;
@@ -1,3 +1,3 @@
1
- export { FILE_UPLOADER_TYPE } from './constants.js';
1
+ export { FILE_UPLOADER_PLACEHOLDER_TYPE, FILE_UPLOADER_TYPE } from './constants.js';
2
2
  export { getFilesFromInput } from './getFilesFromInput.js';
3
3
  export { createFileUploader, createFileUploaderElementByType, insertFileUploaderElement } from './createFileUploader.js';
@@ -1,5 +1,6 @@
1
- import { Editor, QuadratsElement, Path, TransformsInsertNodesOptions, Withable } from '@quadrats/core';
1
+ import { Editor, QuadratsElement, Path, TransformsInsertNodesOptions, Withable, WithElementType, Text } from '@quadrats/core';
2
2
  import { GetFilesFromInputOptions } from './getFilesFromInput';
3
+ export type ImageAccept = 'image/jpeg' | 'image/jpg' | 'image/png';
3
4
  export interface XHRUploadHeaders {
4
5
  [name: string]: string;
5
6
  }
@@ -25,7 +26,7 @@ interface FileUploaderUploadImplementOnProgressArgs {
25
26
  interface FileUploaderUploadImplement {
26
27
  onprogress: ((options: FileUploaderUploadImplementOnProgressArgs) => void) | null;
27
28
  }
28
- interface FileUploaderImplement {
29
+ export interface FileUploaderImplement {
29
30
  onload: (() => void) | null;
30
31
  open: (method: string, url: string | URL) => void;
31
32
  setRequestHeader: (key: string, value: string) => void;
@@ -34,6 +35,9 @@ interface FileUploaderImplement {
34
35
  readonly response: any;
35
36
  readonly upload: FileUploaderUploadImplement;
36
37
  }
38
+ export interface UploaderPlaceholderElement extends QuadratsElement, WithElementType {
39
+ children: [Text];
40
+ }
37
41
  export interface FileUploaderCreateFileUploaderElementOptions {
38
42
  createElement: {
39
43
  [mime in string]?: {
@@ -51,5 +55,7 @@ export interface FileUploader<T extends Editor = Editor> extends Withable {
51
55
  type: string;
52
56
  createFileUploaderElement(editor: T, file: File, options: FileUploaderCreateFileUploaderElementOptions): Promise<FileUploaderElement | undefined>;
53
57
  upload(editor: T, options: FileUploaderUploadOptions): Promise<void>;
58
+ insertUploaderPlaceholder(editor: T): void;
59
+ removeUploaderPlaceholder(editor: T): void;
54
60
  }
55
61
  export {};
@@ -2,6 +2,7 @@ import { Editor, QuadratsElement, GetNodesOptions, Node, NodeEntry, Withable, Wi
2
2
  export type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
3
3
  export interface HeadingElement extends QuadratsElement, WithElementType {
4
4
  level: HeadingLevel;
5
+ align?: 'left' | 'center' | 'right';
5
6
  }
6
7
  export interface WithEnabledHeadingLevels<L extends HeadingLevel> {
7
8
  /**
@@ -3,7 +3,7 @@ import { Range, isNodesTypeIn, getAboveByTypes, Editor, Transforms, createParagr
3
3
  import { IMAGE_TYPES } from './constants.js';
4
4
 
5
5
  function resolveSizeSteps(steps) {
6
- let sortedSteps = steps.filter(step => step > 0 && step < 100).sort();
6
+ let sortedSteps = steps.filter((step) => step > 0 && step < 100).sort();
7
7
  if (!sortedSteps.includes(100)) {
8
8
  sortedSteps = [...sortedSteps, 100];
9
9
  }
@@ -16,12 +16,13 @@ function createImage(options = {}) {
16
16
  const getAboveImageFigure = (editor, options) => getAboveByTypes(editor, [types.figure], options);
17
17
  const getAboveImageCaption = (editor, options) => getAboveByTypes(editor, [types.caption], options);
18
18
  const isNodesInImage = (editor, options) => isNodesTypeIn(editor, [types.image], options);
19
- const isSelectionInImage = editor => isNodesInImage(editor);
20
- const isSelectionInImageCaption = editor => isNodesTypeIn(editor, [types.caption]);
21
- const isCollapsedOnImage = editor => !!editor.selection && Range.isCollapsed(editor.selection) && isSelectionInImage(editor);
19
+ const isSelectionInImage = (editor) => isNodesInImage(editor);
20
+ const isSelectionInImageCaption = (editor) => isNodesTypeIn(editor, [types.caption]);
21
+ const isCollapsedOnImage = (editor) => !!editor.selection && Range.isCollapsed(editor.selection) && isSelectionInImage(editor);
22
22
  const createImageElement = (src, hosting) => {
23
23
  const imageElement = {
24
24
  type: types.image,
25
+ figureType: types.figure,
25
26
  src,
26
27
  hosting,
27
28
  children: [{ text: '' }],
@@ -51,7 +52,7 @@ function createImage(options = {}) {
51
52
  if (!sizeSteps) {
52
53
  return percentage;
53
54
  }
54
- const lowerIndex = sizeSteps.findIndex(step => step >= percentage) - 1;
55
+ const lowerIndex = sizeSteps.findIndex((step) => step >= percentage) - 1;
55
56
  const upperIndex = lowerIndex + 1;
56
57
  if (lowerIndex < 0) {
57
58
  return sizeSteps[0];
@@ -89,7 +90,7 @@ function createImage(options = {}) {
89
90
  insertImage,
90
91
  resizeImage,
91
92
  with(editor) {
92
- const { deleteBackward, deleteForward, insertBreak, isVoid, normalizeNode, } = editor;
93
+ const { deleteBackward, deleteForward, insertBreak, isVoid, normalizeNode } = editor;
93
94
  const deleteCollapsed = (origin, isEdgeMethodName) => {
94
95
  const { selection } = editor;
95
96
  /**
@@ -97,7 +98,7 @@ function createImage(options = {}) {
97
98
  */
98
99
  if (selection && Range.isCollapsed(selection)) {
99
100
  const [, captionPath] = getAboveImageCaption(editor) || [];
100
- if ((captionPath && Editor[isEdgeMethodName](editor, selection.focus, captionPath))) {
101
+ if (captionPath && Editor[isEdgeMethodName](editor, selection.focus, captionPath)) {
101
102
  return;
102
103
  }
103
104
  }
@@ -128,7 +129,7 @@ function createImage(options = {}) {
128
129
  }
129
130
  insertBreak();
130
131
  };
131
- editor.isVoid = element => element.type === types.image || isVoid(element);
132
+ editor.isVoid = (element) => element.type === types.image || isVoid(element);
132
133
  editor.normalizeNode = (entry) => {
133
134
  const [node, path] = entry;
134
135
  if (Element.isElement(node)) {
@@ -140,9 +141,9 @@ function createImage(options = {}) {
140
141
  }
141
142
  else if (node.type === types.image) {
142
143
  const { src, width, hosting } = node;
143
- if (typeof src !== 'string'
144
- || !(width == null || typeof width === 'number')
145
- || !(hosting == null || typeof hosting === 'string')) {
144
+ if (typeof src !== 'string' ||
145
+ !(width == null || typeof width === 'number') ||
146
+ !(hosting == null || typeof hosting === 'string')) {
146
147
  const [, figurePath] = getAboveImageFigure(editor, { at: path }) || [];
147
148
  if (figurePath) {
148
149
  Transforms.removeNodes(editor, { at: figurePath });
@@ -1,6 +1,8 @@
1
1
  import { ImageFigureElement } from './typings';
2
2
  export declare function getImageFigureElementCommonProps(element: ImageFigureElement): {
3
3
  style?: {
4
+ '--qdr-image-align': 'flex-start' | 'center' | 'flex-end';
5
+ '--qdr-image-caption-align': 'left' | 'center' | 'right';
4
6
  width: string;
5
7
  };
6
8
  };
@@ -1,7 +1,33 @@
1
1
  function getImageFigureElementCommonProps(element) {
2
- const { width } = element;
2
+ const { width, align } = element;
3
3
  return {
4
- style: typeof width === 'number' ? { width: `${width}%` } : undefined,
4
+ style: {
5
+ width: typeof width === 'number' ? `${width}%` : 'unset',
6
+ '--qdr-image-align': (() => {
7
+ switch (align) {
8
+ case 'start':
9
+ return 'flex-start';
10
+ case 'center':
11
+ return 'center';
12
+ case 'end':
13
+ return 'flex-end';
14
+ default:
15
+ return 'flex-start';
16
+ }
17
+ })(),
18
+ '--qdr-image-caption-align': (() => {
19
+ switch (align) {
20
+ case 'start':
21
+ return 'left';
22
+ case 'center':
23
+ return 'center';
24
+ case 'end':
25
+ return 'right';
26
+ default:
27
+ return 'left';
28
+ }
29
+ })(),
30
+ },
5
31
  };
6
32
  }
7
33
 
@@ -14,9 +14,35 @@ function isHostingNotRequired(src) {
14
14
  }
15
15
 
16
16
  function getImageFigureElementCommonProps(element) {
17
- const { width } = element;
17
+ const { width, align } = element;
18
18
  return {
19
- style: typeof width === 'number' ? { width: `${width}%` } : undefined,
19
+ style: {
20
+ width: typeof width === 'number' ? `${width}%` : 'unset',
21
+ '--qdr-image-align': (() => {
22
+ switch (align) {
23
+ case 'start':
24
+ return 'flex-start';
25
+ case 'center':
26
+ return 'center';
27
+ case 'end':
28
+ return 'flex-end';
29
+ default:
30
+ return 'flex-start';
31
+ }
32
+ })(),
33
+ '--qdr-image-caption-align': (() => {
34
+ switch (align) {
35
+ case 'start':
36
+ return 'left';
37
+ case 'center':
38
+ return 'center';
39
+ case 'end':
40
+ return 'right';
41
+ default:
42
+ return 'left';
43
+ }
44
+ })(),
45
+ },
20
46
  };
21
47
  }
22
48
 
@@ -29,7 +55,7 @@ function getImageElementCommonProps(element, hostingResolvers) {
29
55
  }
30
56
 
31
57
  function resolveSizeSteps(steps) {
32
- let sortedSteps = steps.filter(step => step > 0 && step < 100).sort();
58
+ let sortedSteps = steps.filter((step) => step > 0 && step < 100).sort();
33
59
  if (!sortedSteps.includes(100)) {
34
60
  sortedSteps = [...sortedSteps, 100];
35
61
  }
@@ -42,12 +68,13 @@ function createImage(options = {}) {
42
68
  const getAboveImageFigure = (editor, options) => core.getAboveByTypes(editor, [types.figure], options);
43
69
  const getAboveImageCaption = (editor, options) => core.getAboveByTypes(editor, [types.caption], options);
44
70
  const isNodesInImage = (editor, options) => core.isNodesTypeIn(editor, [types.image], options);
45
- const isSelectionInImage = editor => isNodesInImage(editor);
46
- const isSelectionInImageCaption = editor => core.isNodesTypeIn(editor, [types.caption]);
47
- const isCollapsedOnImage = editor => !!editor.selection && core.Range.isCollapsed(editor.selection) && isSelectionInImage(editor);
71
+ const isSelectionInImage = (editor) => isNodesInImage(editor);
72
+ const isSelectionInImageCaption = (editor) => core.isNodesTypeIn(editor, [types.caption]);
73
+ const isCollapsedOnImage = (editor) => !!editor.selection && core.Range.isCollapsed(editor.selection) && isSelectionInImage(editor);
48
74
  const createImageElement = (src, hosting) => {
49
75
  const imageElement = {
50
76
  type: types.image,
77
+ figureType: types.figure,
51
78
  src,
52
79
  hosting,
53
80
  children: [{ text: '' }],
@@ -77,7 +104,7 @@ function createImage(options = {}) {
77
104
  if (!sizeSteps) {
78
105
  return percentage;
79
106
  }
80
- const lowerIndex = sizeSteps.findIndex(step => step >= percentage) - 1;
107
+ const lowerIndex = sizeSteps.findIndex((step) => step >= percentage) - 1;
81
108
  const upperIndex = lowerIndex + 1;
82
109
  if (lowerIndex < 0) {
83
110
  return sizeSteps[0];
@@ -115,7 +142,7 @@ function createImage(options = {}) {
115
142
  insertImage,
116
143
  resizeImage,
117
144
  with(editor) {
118
- const { deleteBackward, deleteForward, insertBreak, isVoid, normalizeNode, } = editor;
145
+ const { deleteBackward, deleteForward, insertBreak, isVoid, normalizeNode } = editor;
119
146
  const deleteCollapsed = (origin, isEdgeMethodName) => {
120
147
  const { selection } = editor;
121
148
  /**
@@ -123,7 +150,7 @@ function createImage(options = {}) {
123
150
  */
124
151
  if (selection && core.Range.isCollapsed(selection)) {
125
152
  const [, captionPath] = getAboveImageCaption(editor) || [];
126
- if ((captionPath && core.Editor[isEdgeMethodName](editor, selection.focus, captionPath))) {
153
+ if (captionPath && core.Editor[isEdgeMethodName](editor, selection.focus, captionPath)) {
127
154
  return;
128
155
  }
129
156
  }
@@ -154,7 +181,7 @@ function createImage(options = {}) {
154
181
  }
155
182
  insertBreak();
156
183
  };
157
- editor.isVoid = element => element.type === types.image || isVoid(element);
184
+ editor.isVoid = (element) => element.type === types.image || isVoid(element);
158
185
  editor.normalizeNode = (entry) => {
159
186
  const [node, path] = entry;
160
187
  if (core.Element.isElement(node)) {
@@ -166,9 +193,9 @@ function createImage(options = {}) {
166
193
  }
167
194
  else if (node.type === types.image) {
168
195
  const { src, width, hosting } = node;
169
- if (typeof src !== 'string'
170
- || !(width == null || typeof width === 'number')
171
- || !(hosting == null || typeof hosting === 'string')) {
196
+ if (typeof src !== 'string' ||
197
+ !(width == null || typeof width === 'number') ||
198
+ !(hosting == null || typeof hosting === 'string')) {
172
199
  const [, figurePath] = getAboveImageFigure(editor, { at: path }) || [];
173
200
  if (figurePath) {
174
201
  core.Transforms.removeNodes(editor, { at: figurePath });
@@ -4,11 +4,13 @@ export type ImageTypeKey = 'image';
4
4
  export type ImageCaptionTypeKey = 'caption';
5
5
  export type ImageTypes = Record<ImageFigureTypeKey | ImageTypeKey | ImageCaptionTypeKey, string>;
6
6
  export interface ImageFigureElement extends QuadratsElement, WithElementType {
7
+ align?: 'start' | 'center' | 'end';
7
8
  width?: number;
8
9
  }
9
10
  export interface ImageElement extends QuadratsElement, WithElementType {
10
11
  children: [Text];
11
12
  src: string;
13
+ figureType: string;
12
14
  /**
13
15
  * e.g. The src of image is `8gy9pbaht92y4.jpg` and your static files are hosted by `https://foo.storage`.
14
16
  * Then you can make the hosting of element be `foo`.
@@ -1,5 +1,6 @@
1
1
  import { List, ListTypes } from './typings';
2
2
  export interface CreateListOptions {
3
3
  types?: Partial<ListTypes>;
4
+ labels?: number;
4
5
  }
5
6
  export declare function createList(options?: CreateListOptions): List;
@@ -2,6 +2,8 @@ import { PARAGRAPH_TYPE, isNodesTypeIn, Range, isSelectionAtBlockEdge, deleteSel
2
2
  import { LIST_TYPES } from './constants.js';
3
3
 
4
4
  function createList(options = {}) {
5
+ var _a;
6
+ const labels = (_a = options.labels) !== null && _a !== void 0 ? _a : 4;
5
7
  const types = Object.assign(Object.assign({}, LIST_TYPES), options.types);
6
8
  const isListElement = (node) => [types.ol, types.ul].includes(node.type);
7
9
  const isListItemElement = (node) => node.type === types.li;
@@ -140,6 +142,7 @@ function createList(options = {}) {
140
142
  };
141
143
  return {
142
144
  types,
145
+ labels,
143
146
  isListElement,
144
147
  isListItemElement,
145
148
  isSelectionInList,
package/list/index.cjs.js CHANGED
@@ -9,6 +9,8 @@ const LIST_TYPES = {
9
9
  };
10
10
 
11
11
  function createList(options = {}) {
12
+ var _a;
13
+ const labels = (_a = options.labels) !== null && _a !== void 0 ? _a : 4;
12
14
  const types = Object.assign(Object.assign({}, LIST_TYPES), options.types);
13
15
  const isListElement = (node) => [types.ol, types.ul].includes(node.type);
14
16
  const isListItemElement = (node) => node.type === types.li;
@@ -147,6 +149,7 @@ function createList(options = {}) {
147
149
  };
148
150
  return {
149
151
  types,
152
+ labels,
150
153
  isListElement,
151
154
  isListItemElement,
152
155
  isSelectionInList,
package/list/typings.d.ts CHANGED
@@ -17,6 +17,7 @@ export interface List<T extends Editor = Editor> extends Withable {
17
17
  * An object which keys are `ul`, `ol`, `li` and values are the corresponding element types.
18
18
  */
19
19
  types: ListTypes;
20
+ labels: number;
20
21
  isListElement(node: Node): node is QuadratsElement;
21
22
  isListItemElement(node: Node): node is QuadratsElement;
22
23
  isSelectionInList(editor: T, listTypeKey: ListRootTypeKey): boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quadrats/common",
3
- "version": "0.7.7",
3
+ "version": "1.1.0",
4
4
  "description": "",
5
5
  "author": "Rytass",
6
6
  "homepage": "https://github.com/Quadrats/quadrats#readme",
@@ -18,8 +18,8 @@
18
18
  "url": "https://github.com/Quadrats/quadrats/issues"
19
19
  },
20
20
  "dependencies": {
21
- "@quadrats/core": "^0.7.7",
22
- "@quadrats/locales": "^0.7.7",
23
- "@quadrats/utils": "^0.7.2"
21
+ "@quadrats/core": "^1.1.0",
22
+ "@quadrats/locales": "^1.0.0",
23
+ "@quadrats/utils": "^1.0.0"
24
24
  }
25
25
  }
@@ -0,0 +1,2 @@
1
+ import { Paragraph } from './typings';
2
+ export declare function createParagraph(): Paragraph;
@@ -0,0 +1,24 @@
1
+ import { getNodes, PARAGRAPH_TYPE, Transforms } from '@quadrats/core';
2
+
3
+ function createParagraph() {
4
+ const getParagraphNodes = (editor, options = {}) => getNodes(editor, Object.assign(Object.assign({}, options), { match: (node) => node.type === PARAGRAPH_TYPE }));
5
+ const isSelectionInParagraph = (editor, options = {}) => {
6
+ const [match] = getParagraphNodes(editor, options);
7
+ return !!match;
8
+ };
9
+ const setParagraphNodes = (editor) => {
10
+ const paragraph = { type: PARAGRAPH_TYPE, children: [] };
11
+ Transforms.setNodes(editor, paragraph);
12
+ };
13
+ return {
14
+ type: PARAGRAPH_TYPE,
15
+ getParagraphNodes,
16
+ isSelectionInParagraph,
17
+ setParagraphNodes,
18
+ with(editor) {
19
+ return editor;
20
+ },
21
+ };
22
+ }
23
+
24
+ export { createParagraph };
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+
3
+ var core = require('@quadrats/core');
4
+
5
+ function createParagraph() {
6
+ const getParagraphNodes = (editor, options = {}) => core.getNodes(editor, Object.assign(Object.assign({}, options), { match: (node) => node.type === core.PARAGRAPH_TYPE }));
7
+ const isSelectionInParagraph = (editor, options = {}) => {
8
+ const [match] = getParagraphNodes(editor, options);
9
+ return !!match;
10
+ };
11
+ const setParagraphNodes = (editor) => {
12
+ const paragraph = { type: core.PARAGRAPH_TYPE, children: [] };
13
+ core.Transforms.setNodes(editor, paragraph);
14
+ };
15
+ return {
16
+ type: core.PARAGRAPH_TYPE,
17
+ getParagraphNodes,
18
+ isSelectionInParagraph,
19
+ setParagraphNodes,
20
+ with(editor) {
21
+ return editor;
22
+ },
23
+ };
24
+ }
25
+
26
+ exports.createParagraph = createParagraph;
@@ -0,0 +1,2 @@
1
+ export * from './typings';
2
+ export * from './createParagraph';
@@ -0,0 +1 @@
1
+ export { createParagraph } from './createParagraph.js';
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "@quadrats/common/paragraph",
3
+ "sideEffects": false,
4
+ "main": "./index.cjs.js",
5
+ "module": "./index.js",
6
+ "typings": "./index.d.ts"
7
+ }
@@ -0,0 +1,9 @@
1
+ import { Editor, QuadratsElement, GetNodesOptions, Node, NodeEntry, Withable, WithElementType } from '@quadrats/core';
2
+ export interface ParagraphElement extends QuadratsElement {
3
+ align?: 'left' | 'center' | 'right';
4
+ }
5
+ export interface Paragraph<T extends Editor = Editor> extends WithElementType, Withable {
6
+ getParagraphNodes(editor: T, options?: GetNodesOptions): Generator<NodeEntry<Node>>;
7
+ isSelectionInParagraph(editor: T, options?: GetNodesOptions): boolean;
8
+ setParagraphNodes(editor: T): void;
9
+ }
@@ -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>;