ckeditor5-elements-attributes 0.0.0-stage → 49.0.0-alpha.2

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ivan Kildyushov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,32 @@
1
- # Temporary Holding Version
1
+ # ckeditor5-elements-attributes
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Element attributes for CKEditor 5 Elements: `ElementAttributes` registers the `showElementAttributes` command, which shows
4
+ the attributes of an element, as key-value pairs, in CKEditor's modal dialog.
5
+
6
+ ## Installation
7
+
8
+ This package is part of `ckeditor5-elements`. Install the whole package to use it:
9
+
10
+ ```sh
11
+ npm install ckeditor5 ckeditor5-elements
12
+ ```
13
+
14
+ ## Usage
15
+
16
+ ```ts
17
+ import { ElementAttributes } from 'ckeditor5-elements';
18
+ import 'ckeditor5-elements/index.css';
19
+
20
+ // In the editor config: it is a command, so it can be a menu item, a toolbar button, or a callback.
21
+ plugins: [..., ElementAttributes],
22
+ elementContextMenu: (element, editor) => [editor.commands.get('showElementAttributes')]
23
+
24
+ // From code:
25
+ editor.commands.get('showElementAttributes').executeFor(element);
26
+ ```
27
+
28
+ See the [Attributes guide](https://ivankild.github.io/ckeditor5-elements/guide/attributes) of the documentation.
29
+
30
+ ## License
31
+
32
+ MIT
@@ -0,0 +1,10 @@
1
+ import type { ElementAttributes, ElementAttributesCommand } from './index.js';
2
+ declare module 'ckeditor5' {
3
+ interface PluginsMap {
4
+ [ElementAttributes.pluginName]: ElementAttributes;
5
+ }
6
+ interface CommandsMap {
7
+ showElementAttributes: ElementAttributesCommand;
8
+ }
9
+ }
10
+ //# sourceMappingURL=augmentation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"augmentation.d.ts","sourceRoot":"","sources":["../src/augmentation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAE9E,OAAO,QAAQ,WAAW,CAAC;IAC1B,UAAU,UAAU;QACnB,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE,iBAAiB,CAAC;KAClD;IAED,UAAU,WAAW;QACpB,qBAAqB,EAAE,wBAAwB,CAAC;KAChD;CACD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=augmentation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"augmentation.js","sourceRoot":"","sources":["../src/augmentation.ts"],"names":[],"mappings":""}
@@ -0,0 +1,18 @@
1
+ import { Dialog, Plugin } from 'ckeditor5';
2
+ /**
3
+ * Registers the `showElementAttributes` command, which shows the attributes of an element, as key-value pairs, in a
4
+ * modal dialog.
5
+ *
6
+ * ```ts
7
+ * editor.commands.get('showElementAttributes').executeFor(element);
8
+ * ```
9
+ *
10
+ * The command has a title and an icon, so it can be a menu item (e.g. in the `elementContextMenu` config of
11
+ * `ElementContextMenu`), a toolbar button, or the callback of a clickable element (see `ElementClickable`).
12
+ */
13
+ export default class ElementAttributes extends Plugin {
14
+ static get requires(): readonly [typeof Dialog];
15
+ static get pluginName(): 'ElementAttributes';
16
+ init(): void;
17
+ }
18
+ //# sourceMappingURL=elementAttributes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elementAttributes.d.ts","sourceRoot":"","sources":["../src/elementAttributes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAG3C;;;;;;;;;;GAUG;AACH,MAAM,CAAC,OAAO,OAAO,iBAAkB,SAAQ,MAAM;IACpD,WAAkB,QAAQ,IAAI,SAAS,CAAC,OAAO,MAAM,CAAC,CAErD;IAED,WAAkB,UAAU,IAAI,mBAAmB,CAElD;IAEM,IAAI,IAAI,IAAI;CAGnB"}
@@ -0,0 +1,25 @@
1
+ import { Dialog, Plugin } from 'ckeditor5';
2
+ import ElementAttributesCommand from './elementAttributesCommand.js';
3
+ /**
4
+ * Registers the `showElementAttributes` command, which shows the attributes of an element, as key-value pairs, in a
5
+ * modal dialog.
6
+ *
7
+ * ```ts
8
+ * editor.commands.get('showElementAttributes').executeFor(element);
9
+ * ```
10
+ *
11
+ * The command has a title and an icon, so it can be a menu item (e.g. in the `elementContextMenu` config of
12
+ * `ElementContextMenu`), a toolbar button, or the callback of a clickable element (see `ElementClickable`).
13
+ */
14
+ export default class ElementAttributes extends Plugin {
15
+ static get requires() {
16
+ return [Dialog];
17
+ }
18
+ static get pluginName() {
19
+ return 'ElementAttributes';
20
+ }
21
+ init() {
22
+ this.editor.commands.add('showElementAttributes', new ElementAttributesCommand(this.editor));
23
+ }
24
+ }
25
+ //# sourceMappingURL=elementAttributes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elementAttributes.js","sourceRoot":"","sources":["../src/elementAttributes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,wBAAwB,MAAM,+BAA+B,CAAC;AAErE;;;;;;;;;;GAUG;AACH,MAAM,CAAC,OAAO,OAAO,iBAAkB,SAAQ,MAAM;IAC7C,MAAM,KAAK,QAAQ;QACzB,OAAO,CAAC,MAAM,CAAU,CAAC;IAC1B,CAAC;IAEM,MAAM,KAAK,UAAU;QAC3B,OAAO,mBAA4B,CAAC;IACrC,CAAC;IAEM,IAAI;QACV,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,uBAAuB,EAAE,IAAI,wBAAwB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAC9F,CAAC;CACD"}
@@ -0,0 +1,23 @@
1
+ import { type Editor } from 'ckeditor5';
2
+ import { ElementOrPositionCommand, type ElementOrPosition } from 'ckeditor5-elements-core';
3
+ /**
4
+ * Shows the attributes of an element, as key-value pairs, in CKEditor's modal dialog.
5
+ *
6
+ * The element is the given one, the parent of the given position, or the selected element or the parent of the
7
+ * selection (see {@link ElementOrPositionCommand}). It does not change the data, so it works in read-only mode.
8
+ *
9
+ * Strings are shown as they are, other values (numbers, booleans, objects) as JSON. Long values are cut.
10
+ */
11
+ export default class ElementAttributesCommand extends ElementOrPositionCommand {
12
+ constructor(editor: Editor);
13
+ /**
14
+ * Returns the attributes of the element as key-value pairs of text, as the dialog shows them.
15
+ */
16
+ getAttributes(elementOrPosition?: ElementOrPosition): [key: string, value: string][];
17
+ /**
18
+ * Shows the dialog with the attributes of the element, in place of the one that is open.
19
+ */
20
+ execute(elementOrPosition?: ElementOrPosition): void;
21
+ protected _isEnabledFor(elementOrPosition?: ElementOrPosition): boolean;
22
+ }
23
+ //# sourceMappingURL=elementAttributesCommand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elementAttributesCommand.d.ts","sourceRoot":"","sources":["../src/elementAttributesCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,wBAAwB,EAAE,KAAK,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAS3F;;;;;;;GAOG;AACH,MAAM,CAAC,OAAO,OAAO,wBAAyB,SAAQ,wBAAwB;gBACjE,MAAM,EAAE,MAAM;IAU1B;;OAEG;IACI,aAAa,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE;IAM3F;;OAEG;IACa,OAAO,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,IAAI;cA2BjD,aAAa,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,OAAO;CAGhF"}
@@ -0,0 +1,66 @@
1
+ import { Dialog } from 'ckeditor5';
2
+ import { ElementOrPositionCommand } from 'ckeditor5-elements-core';
3
+ import ElementAttributesView from './elementAttributesView.js';
4
+ import { attributesIcon } from './icons.js';
5
+ /**
6
+ * The longest value shown in full. Longer ones, e.g. the data of an image, are cut.
7
+ */
8
+ const MAX_VALUE_LENGTH = 120;
9
+ /**
10
+ * Shows the attributes of an element, as key-value pairs, in CKEditor's modal dialog.
11
+ *
12
+ * The element is the given one, the parent of the given position, or the selected element or the parent of the
13
+ * selection (see {@link ElementOrPositionCommand}). It does not change the data, so it works in read-only mode.
14
+ *
15
+ * Strings are shown as they are, other values (numbers, booleans, objects) as JSON. Long values are cut.
16
+ */
17
+ export default class ElementAttributesCommand extends ElementOrPositionCommand {
18
+ constructor(editor) {
19
+ super(editor);
20
+ this.title = editor.t('Show attributes');
21
+ this.icon = attributesIcon;
22
+ // It only reads the element.
23
+ this.affectsData = false;
24
+ }
25
+ /**
26
+ * Returns the attributes of the element as key-value pairs of text, as the dialog shows them.
27
+ */
28
+ getAttributes(elementOrPosition) {
29
+ const element = this._getElement(elementOrPosition);
30
+ return element ? Array.from(element.getAttributes(), ([key, value]) => [key, formatValue(value)]) : [];
31
+ }
32
+ /**
33
+ * Shows the dialog with the attributes of the element, in place of the one that is open.
34
+ */
35
+ execute(elementOrPosition) {
36
+ const editor = this.editor;
37
+ const element = this._getElement(elementOrPosition);
38
+ if (!element) {
39
+ return;
40
+ }
41
+ const dialog = editor.plugins.get(Dialog);
42
+ dialog.show({
43
+ id: 'elementAttributes',
44
+ isModal: true,
45
+ title: `<${element.name}>`,
46
+ content: new ElementAttributesView(editor.locale, this.getAttributes(element), editor.t('No attributes')),
47
+ actionButtons: [
48
+ {
49
+ label: editor.t('Close'),
50
+ withText: true,
51
+ onExecute: () => {
52
+ dialog.hide();
53
+ }
54
+ }
55
+ ]
56
+ });
57
+ }
58
+ _isEnabledFor(elementOrPosition) {
59
+ return !!this._getElement(elementOrPosition);
60
+ }
61
+ }
62
+ function formatValue(value) {
63
+ const text = typeof value === 'string' ? value : JSON.stringify(value);
64
+ return text.length > MAX_VALUE_LENGTH ? `${text.slice(0, MAX_VALUE_LENGTH - 1)}…` : text;
65
+ }
66
+ //# sourceMappingURL=elementAttributesCommand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elementAttributesCommand.js","sourceRoot":"","sources":["../src/elementAttributesCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAe,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,wBAAwB,EAA0B,MAAM,yBAAyB,CAAC;AAC3F,OAAO,qBAAqB,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C;;GAEG;AACH,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAE7B;;;;;;;GAOG;AACH,MAAM,CAAC,OAAO,OAAO,wBAAyB,SAAQ,wBAAwB;IAC7E,YAAY,MAAc;QACzB,KAAK,CAAC,MAAM,CAAC,CAAC;QAEd,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;QAE3B,6BAA6B;QAC7B,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;IAC1B,CAAC;IAED;;OAEG;IACI,aAAa,CAAC,iBAAqC;QACzD,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAAC,CAAC;QAEpD,OAAO,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACxG,CAAC;IAED;;OAEG;IACa,OAAO,CAAC,iBAAqC;QAC5D,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAAC,CAAC;QAEpD,IAAI,CAAC,OAAO,EAAE,CAAC;YACd,OAAO;QACR,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAE1C,MAAM,CAAC,IAAI,CAAC;YACX,EAAE,EAAE,mBAAmB;YACvB,OAAO,EAAE,IAAI;YACb,KAAK,EAAE,IAAI,OAAO,CAAC,IAAI,GAAG;YAC1B,OAAO,EAAE,IAAI,qBAAqB,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;YACzG,aAAa,EAAE;gBACd;oBACC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;oBACxB,QAAQ,EAAE,IAAI;oBACd,SAAS,EAAE,GAAG,EAAE;wBACf,MAAM,CAAC,IAAI,EAAE,CAAC;oBACf,CAAC;iBACD;aACD;SACD,CAAC,CAAC;IACJ,CAAC;IAEkB,aAAa,CAAC,iBAAqC;QACrE,OAAO,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAAC,CAAC;IAC9C,CAAC;CACD;AAED,SAAS,WAAW,CAAC,KAAc;IAClC,MAAM,IAAI,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAEvE,OAAO,IAAI,CAAC,MAAM,GAAG,gBAAgB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,gBAAgB,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1F,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { View, type Locale } from 'ckeditor5';
2
+ /**
3
+ * The content of the attributes dialog: a table of the attributes of an element, a row for each, with the key and the
4
+ * value as text.
5
+ */
6
+ export default class ElementAttributesView extends View {
7
+ constructor(locale: Locale, attributes: readonly (readonly [key: string, value: string])[], emptyText: string);
8
+ }
9
+ //# sourceMappingURL=elementAttributesView.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elementAttributesView.d.ts","sourceRoot":"","sources":["../src/elementAttributesView.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AAE9C;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,qBAAsB,SAAQ,IAAI;gBAC1C,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM;CA+B7G"}
@@ -0,0 +1,37 @@
1
+ import { View } from 'ckeditor5';
2
+ /**
3
+ * The content of the attributes dialog: a table of the attributes of an element, a row for each, with the key and the
4
+ * value as text.
5
+ */
6
+ export default class ElementAttributesView extends View {
7
+ constructor(locale, attributes, emptyText) {
8
+ super(locale);
9
+ const rows = attributes.length
10
+ ? attributes.map(([key, value]) => ({
11
+ tag: 'tr',
12
+ children: [
13
+ { tag: 'th', attributes: { scope: 'row' }, children: [{ text: key }] },
14
+ { tag: 'td', children: [{ text: value }] }
15
+ ]
16
+ }))
17
+ : [
18
+ {
19
+ tag: 'tr',
20
+ children: [
21
+ {
22
+ tag: 'td',
23
+ attributes: { class: 'ck-elements-attributes__empty' },
24
+ children: [{ text: emptyText }]
25
+ }
26
+ ]
27
+ }
28
+ ];
29
+ // CKEditor's reset styles all elements of its UI; `ck-reset_all-excluded` leaves the table in it to our styles.
30
+ this.setTemplate({
31
+ tag: 'div',
32
+ attributes: { class: ['ck-reset_all-excluded', 'ck-elements-attributes'] },
33
+ children: [{ tag: 'table', children: rows }]
34
+ });
35
+ }
36
+ }
37
+ //# sourceMappingURL=elementAttributesView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elementAttributesView.js","sourceRoot":"","sources":["../src/elementAttributesView.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAe,MAAM,WAAW,CAAC;AAE9C;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,qBAAsB,SAAQ,IAAI;IACtD,YAAY,MAAc,EAAE,UAA8D,EAAE,SAAiB;QAC5G,KAAK,CAAC,MAAM,CAAC,CAAC;QAEd,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM;YAC7B,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;gBAClC,GAAG,EAAE,IAAI;gBACT,QAAQ,EAAE;oBACT,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE;oBACtE,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE;iBAC1C;aACD,CAAC,CAAC;YACJ,CAAC,CAAC;gBACA;oBACC,GAAG,EAAE,IAAI;oBACT,QAAQ,EAAE;wBACT;4BACC,GAAG,EAAE,IAAI;4BACT,UAAU,EAAE,EAAE,KAAK,EAAE,+BAA+B,EAAE;4BACtD,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;yBAC/B;qBACD;iBACD;aACD,CAAC;QAEJ,gHAAgH;QAChH,IAAI,CAAC,WAAW,CAAC;YAChB,GAAG,EAAE,KAAK;YACV,UAAU,EAAE,EAAE,KAAK,EAAE,CAAC,uBAAuB,EAAE,wBAAwB,CAAC,EAAE;YAC1E,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;SAC5C,CAAC,CAAC;IACJ,CAAC;CACD"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * The icon of the command: CKEditor's own info icon.
3
+ */
4
+ export declare const attributesIcon: string;
5
+ //# sourceMappingURL=icons.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../src/icons.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,eAAO,MAAM,cAAc,QAAW,CAAC"}
package/dist/icons.js ADDED
@@ -0,0 +1,6 @@
1
+ import { IconInfo } from 'ckeditor5';
2
+ /**
3
+ * The icon of the command: CKEditor's own info icon.
4
+ */
5
+ export const attributesIcon = IconInfo;
6
+ //# sourceMappingURL=icons.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icons.js","sourceRoot":"","sources":["../src/icons.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,QAAQ,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Element attributes: show the attributes of an element, as key-value pairs, in a modal dialog.
3
+ *
4
+ * @module ckeditor5-elements-attributes
5
+ */
6
+ export { default as ElementAttributes } from './elementAttributes.js';
7
+ export { default as ElementAttributesCommand } from './elementAttributesCommand.js';
8
+ export { default as ElementAttributesView } from './elementAttributesView.js';
9
+ export { attributesIcon } from './icons.js';
10
+ import './augmentation.js';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAGtE,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAGpF,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAG9E,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,OAAO,mBAAmB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Element attributes: show the attributes of an element, as key-value pairs, in a modal dialog.
3
+ *
4
+ * @module ckeditor5-elements-attributes
5
+ */
6
+ // Plugins.
7
+ export { default as ElementAttributes } from './elementAttributes.js';
8
+ // Commands.
9
+ export { default as ElementAttributesCommand } from './elementAttributesCommand.js';
10
+ // Views.
11
+ export { default as ElementAttributesView } from './elementAttributesView.js';
12
+ // Icons.
13
+ export { attributesIcon } from './icons.js';
14
+ import './augmentation.js';
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,WAAW;AACX,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEtE,YAAY;AACZ,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAEpF,SAAS;AACT,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAE9E,SAAS;AACT,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,OAAO,mBAAmB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,52 @@
1
1
  {
2
2
  "name": "ckeditor5-elements-attributes",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "49.0.0-alpha.2",
4
+ "description": "Element attributes for CKEditor 5: show the attributes of an element, as key-value pairs, in a modal dialog.",
5
+ "keywords": [
6
+ "ckeditor",
7
+ "ckeditor5",
8
+ "ckeditor 5",
9
+ "ckeditor5-feature",
10
+ "ckeditor5-plugin"
11
+ ],
12
+ "license": "MIT",
13
+ "author": "Ivan Kildyushov",
14
+ "homepage": "https://ivankild.github.io/ckeditor5-elements/guide/attributes",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/ivankild/ckeditor5-elements.git",
18
+ "directory": "packages/ckeditor5-elements-attributes"
19
+ },
20
+ "bugs": {
21
+ "url": "https://github.com/ivankild/ckeditor5-elements/issues"
22
+ },
23
+ "type": "module",
24
+ "main": "./dist/index.js",
25
+ "types": "./dist/index.d.ts",
26
+ "exports": {
27
+ ".": {
28
+ "types": "./dist/index.d.ts",
29
+ "import": "./dist/index.js"
30
+ },
31
+ "./index.css": "./theme/elementAttributes.css",
32
+ "./package.json": "./package.json"
33
+ },
34
+ "files": [
35
+ "dist",
36
+ "src",
37
+ "theme",
38
+ "README.md"
39
+ ],
40
+ "sideEffects": [
41
+ "*.css"
42
+ ],
43
+ "dependencies": {
44
+ "ckeditor5-elements-core": "49.0.0-alpha.2"
45
+ },
46
+ "peerDependencies": {
47
+ "ckeditor5": "^49.0.0"
48
+ },
49
+ "scripts": {
50
+ "build": "tsc --build"
51
+ }
6
52
  }
@@ -0,0 +1,11 @@
1
+ import type { ElementAttributes, ElementAttributesCommand } from './index.js';
2
+
3
+ declare module 'ckeditor5' {
4
+ interface PluginsMap {
5
+ [ElementAttributes.pluginName]: ElementAttributes;
6
+ }
7
+
8
+ interface CommandsMap {
9
+ showElementAttributes: ElementAttributesCommand;
10
+ }
11
+ }
@@ -0,0 +1,27 @@
1
+ import { Dialog, Plugin } from 'ckeditor5';
2
+ import ElementAttributesCommand from './elementAttributesCommand.js';
3
+
4
+ /**
5
+ * Registers the `showElementAttributes` command, which shows the attributes of an element, as key-value pairs, in a
6
+ * modal dialog.
7
+ *
8
+ * ```ts
9
+ * editor.commands.get('showElementAttributes').executeFor(element);
10
+ * ```
11
+ *
12
+ * The command has a title and an icon, so it can be a menu item (e.g. in the `elementContextMenu` config of
13
+ * `ElementContextMenu`), a toolbar button, or the callback of a clickable element (see `ElementClickable`).
14
+ */
15
+ export default class ElementAttributes extends Plugin {
16
+ public static get requires(): readonly [typeof Dialog] {
17
+ return [Dialog] as const;
18
+ }
19
+
20
+ public static get pluginName(): 'ElementAttributes' {
21
+ return 'ElementAttributes' as const;
22
+ }
23
+
24
+ public init(): void {
25
+ this.editor.commands.add('showElementAttributes', new ElementAttributesCommand(this.editor));
26
+ }
27
+ }
@@ -0,0 +1,78 @@
1
+ import { Dialog, type Editor } from 'ckeditor5';
2
+ import { ElementOrPositionCommand, type ElementOrPosition } from 'ckeditor5-elements-core';
3
+ import ElementAttributesView from './elementAttributesView.js';
4
+ import { attributesIcon } from './icons.js';
5
+
6
+ /**
7
+ * The longest value shown in full. Longer ones, e.g. the data of an image, are cut.
8
+ */
9
+ const MAX_VALUE_LENGTH = 120;
10
+
11
+ /**
12
+ * Shows the attributes of an element, as key-value pairs, in CKEditor's modal dialog.
13
+ *
14
+ * The element is the given one, the parent of the given position, or the selected element or the parent of the
15
+ * selection (see {@link ElementOrPositionCommand}). It does not change the data, so it works in read-only mode.
16
+ *
17
+ * Strings are shown as they are, other values (numbers, booleans, objects) as JSON. Long values are cut.
18
+ */
19
+ export default class ElementAttributesCommand extends ElementOrPositionCommand {
20
+ constructor(editor: Editor) {
21
+ super(editor);
22
+
23
+ this.title = editor.t('Show attributes');
24
+ this.icon = attributesIcon;
25
+
26
+ // It only reads the element.
27
+ this.affectsData = false;
28
+ }
29
+
30
+ /**
31
+ * Returns the attributes of the element as key-value pairs of text, as the dialog shows them.
32
+ */
33
+ public getAttributes(elementOrPosition?: ElementOrPosition): [key: string, value: string][] {
34
+ const element = this._getElement(elementOrPosition);
35
+
36
+ return element ? Array.from(element.getAttributes(), ([key, value]) => [key, formatValue(value)]) : [];
37
+ }
38
+
39
+ /**
40
+ * Shows the dialog with the attributes of the element, in place of the one that is open.
41
+ */
42
+ public override execute(elementOrPosition?: ElementOrPosition): void {
43
+ const editor = this.editor;
44
+ const element = this._getElement(elementOrPosition);
45
+
46
+ if (!element) {
47
+ return;
48
+ }
49
+
50
+ const dialog = editor.plugins.get(Dialog);
51
+
52
+ dialog.show({
53
+ id: 'elementAttributes',
54
+ isModal: true,
55
+ title: `<${element.name}>`,
56
+ content: new ElementAttributesView(editor.locale, this.getAttributes(element), editor.t('No attributes')),
57
+ actionButtons: [
58
+ {
59
+ label: editor.t('Close'),
60
+ withText: true,
61
+ onExecute: () => {
62
+ dialog.hide();
63
+ }
64
+ }
65
+ ]
66
+ });
67
+ }
68
+
69
+ protected override _isEnabledFor(elementOrPosition?: ElementOrPosition): boolean {
70
+ return !!this._getElement(elementOrPosition);
71
+ }
72
+ }
73
+
74
+ function formatValue(value: unknown): string {
75
+ const text = typeof value === 'string' ? value : JSON.stringify(value);
76
+
77
+ return text.length > MAX_VALUE_LENGTH ? `${text.slice(0, MAX_VALUE_LENGTH - 1)}…` : text;
78
+ }
@@ -0,0 +1,39 @@
1
+ import { View, type Locale } from 'ckeditor5';
2
+
3
+ /**
4
+ * The content of the attributes dialog: a table of the attributes of an element, a row for each, with the key and the
5
+ * value as text.
6
+ */
7
+ export default class ElementAttributesView extends View {
8
+ constructor(locale: Locale, attributes: readonly (readonly [key: string, value: string])[], emptyText: string) {
9
+ super(locale);
10
+
11
+ const rows = attributes.length
12
+ ? attributes.map(([key, value]) => ({
13
+ tag: 'tr',
14
+ children: [
15
+ { tag: 'th', attributes: { scope: 'row' }, children: [{ text: key }] },
16
+ { tag: 'td', children: [{ text: value }] }
17
+ ]
18
+ }))
19
+ : [
20
+ {
21
+ tag: 'tr',
22
+ children: [
23
+ {
24
+ tag: 'td',
25
+ attributes: { class: 'ck-elements-attributes__empty' },
26
+ children: [{ text: emptyText }]
27
+ }
28
+ ]
29
+ }
30
+ ];
31
+
32
+ // CKEditor's reset styles all elements of its UI; `ck-reset_all-excluded` leaves the table in it to our styles.
33
+ this.setTemplate({
34
+ tag: 'div',
35
+ attributes: { class: ['ck-reset_all-excluded', 'ck-elements-attributes'] },
36
+ children: [{ tag: 'table', children: rows }]
37
+ });
38
+ }
39
+ }
package/src/icons.ts ADDED
@@ -0,0 +1,6 @@
1
+ import { IconInfo } from 'ckeditor5';
2
+
3
+ /**
4
+ * The icon of the command: CKEditor's own info icon.
5
+ */
6
+ export const attributesIcon = IconInfo;
package/src/index.ts ADDED
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Element attributes: show the attributes of an element, as key-value pairs, in a modal dialog.
3
+ *
4
+ * @module ckeditor5-elements-attributes
5
+ */
6
+
7
+ // Plugins.
8
+ export { default as ElementAttributes } from './elementAttributes.js';
9
+
10
+ // Commands.
11
+ export { default as ElementAttributesCommand } from './elementAttributesCommand.js';
12
+
13
+ // Views.
14
+ export { default as ElementAttributesView } from './elementAttributesView.js';
15
+
16
+ // Icons.
17
+ export { attributesIcon } from './icons.js';
18
+
19
+ import './augmentation.js';
@@ -0,0 +1,30 @@
1
+ /*
2
+ * The table of the attributes dialog. It is excluded from CKEditor's reset (`ck-reset_all-excluded`), so it has its own
3
+ * styles.
4
+ */
5
+ .ck-elements-attributes table {
6
+ width: min(32em, 80vw);
7
+ border-collapse: collapse;
8
+ table-layout: fixed;
9
+ }
10
+
11
+ .ck-elements-attributes th,
12
+ .ck-elements-attributes td {
13
+ padding: 0.3em 0.8em;
14
+ border-bottom: 1px solid var(--ck-color-base-border);
15
+ text-align: left;
16
+ vertical-align: top;
17
+ /* The dialog does not wrap its content, but long values, such as the data of an image, must wrap. */
18
+ white-space: normal;
19
+ overflow-wrap: anywhere;
20
+ }
21
+
22
+ .ck-elements-attributes th {
23
+ width: 7em;
24
+ font-weight: 600;
25
+ }
26
+
27
+ .ck-elements-attributes .ck-elements-attributes__empty {
28
+ color: var(--ck-color-text);
29
+ opacity: 0.65;
30
+ }