@inshapardaz/likhari-react 0.1.18-dev.154 → 0.1.18-dev.158
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/blocks/PoetryNode.d.ts +22 -15
- package/dist/blocks/PoetryNode.d.ts.map +1 -1
- package/dist/blocks/PoetryNode.js +43 -22
- package/dist/blocks/poetryActions.d.ts +30 -36
- package/dist/blocks/poetryActions.d.ts.map +1 -1
- package/dist/blocks/poetryActions.js +141 -130
- package/dist/components/Toolbar.d.ts.map +1 -1
- package/dist/components/Toolbar.js +14 -25
- package/dist/i18n/strings.d.ts +4 -3
- package/dist/i18n/strings.d.ts.map +1 -1
- package/dist/i18n/strings.js +12 -9
- package/dist/nodes.d.ts.map +1 -1
- package/dist/nodes.js +0 -2
- package/dist/plugins/PoetryPlugin.d.ts.map +1 -1
- package/dist/plugins/PoetryPlugin.js +2 -3
- package/dist/theme/editor.css +31 -50
- package/dist/theme/editorTheme.d.ts.map +1 -1
- package/dist/theme/editorTheme.js +0 -1
- package/package.json +1 -1
- package/dist/blocks/PoetryCoupletNode.d.ts +0 -36
- package/dist/blocks/PoetryCoupletNode.d.ts.map +0 -1
- package/dist/blocks/PoetryCoupletNode.js +0 -85
|
@@ -1,24 +1,28 @@
|
|
|
1
1
|
import { type DOMConversionMap, type DOMExportOutput, type EditorConfig, type LexicalNode, type NodeKey, type SerializedElementNode, type Spread, ElementNode } from 'lexical';
|
|
2
|
-
export type PoetryLayout = 'single' | 'two-column'
|
|
2
|
+
export type PoetryLayout = 'single' | 'two-column';
|
|
3
3
|
export type PoetryAlign = 'justify' | 'left' | 'right' | 'start';
|
|
4
|
+
/** Vertical space between couplets — an ordered scale the menu steps through. */
|
|
5
|
+
export declare const POETRY_SPACINGS: readonly ["compact", "normal", "relaxed", "loose"];
|
|
6
|
+
export type PoetrySpacing = (typeof POETRY_SPACINGS)[number];
|
|
7
|
+
export declare const DEFAULT_POETRY_SPACING: PoetrySpacing;
|
|
4
8
|
export type SerializedPoetryBlockNode = Spread<{
|
|
5
9
|
layout: PoetryLayout;
|
|
6
10
|
align: PoetryAlign;
|
|
7
11
|
width?: number;
|
|
12
|
+
spacing?: PoetrySpacing;
|
|
8
13
|
}, SerializedElementNode>;
|
|
9
14
|
/**
|
|
10
|
-
* A poetry *section*: one or more couplets (two-line verse units)
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* restructured/grown. `layout`
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* in place of four fixed templates, per requirements doc §4.11.
|
|
15
|
+
* A poetry *section*: one or more couplets (two-line verse units) sharing
|
|
16
|
+
* one layout — single-column stacks each couplet's two misras directly as
|
|
17
|
+
* paragraph children (two per couplet, in order), two-column gives each
|
|
18
|
+
* couplet its own LayoutContainerNode row (built on the columns primitive,
|
|
19
|
+
* §4.9) — see blocks/poetryActions.ts's $getCouplets for how either shape
|
|
20
|
+
* is read, and $setPoetryLayout/$exitPoetryOnEnter for how children are
|
|
21
|
+
* restructured/grown between couplets and layouts. `layout` and `align`
|
|
22
|
+
* apply to the whole section, not per couplet; both mutate in place via
|
|
23
|
+
* poetryActions so converting a section between layouts doesn't lose
|
|
24
|
+
* selection/undo coherence. One extensible primitive in place of four
|
|
25
|
+
* fixed templates, per requirements doc §4.11.
|
|
22
26
|
*/
|
|
23
27
|
export declare class PoetryBlockNode extends ElementNode {
|
|
24
28
|
__layout: PoetryLayout;
|
|
@@ -26,7 +30,8 @@ export declare class PoetryBlockNode extends ElementNode {
|
|
|
26
30
|
/** User-chosen width in px (drag-resized), overriding editor.css's default
|
|
27
31
|
* max-width: 70%. Undefined until the user resizes it. */
|
|
28
32
|
__width?: number;
|
|
29
|
-
|
|
33
|
+
__spacing: PoetrySpacing;
|
|
34
|
+
constructor(layout?: PoetryLayout, align?: PoetryAlign, width?: number, spacing?: PoetrySpacing, key?: NodeKey);
|
|
30
35
|
static getType(): string;
|
|
31
36
|
static clone(node: PoetryBlockNode): PoetryBlockNode;
|
|
32
37
|
getLayout(): PoetryLayout;
|
|
@@ -37,6 +42,8 @@ export declare class PoetryBlockNode extends ElementNode {
|
|
|
37
42
|
* poetryActions.ts's $setPoetryLayout, not a node method, since it needs
|
|
38
43
|
* $-context tree mutations beyond this node's own state. */
|
|
39
44
|
setLayoutAttribute(layout: PoetryLayout): this;
|
|
45
|
+
getSpacing(): PoetrySpacing;
|
|
46
|
+
setSpacing(spacing: PoetrySpacing): this;
|
|
40
47
|
setAlign(align: PoetryAlign): this;
|
|
41
48
|
static importJSON(serializedNode: SerializedPoetryBlockNode): PoetryBlockNode;
|
|
42
49
|
exportJSON(): SerializedPoetryBlockNode;
|
|
@@ -47,6 +54,6 @@ export declare class PoetryBlockNode extends ElementNode {
|
|
|
47
54
|
canBeEmpty(): false;
|
|
48
55
|
isShadowRoot(): boolean;
|
|
49
56
|
}
|
|
50
|
-
export declare function $createPoetryBlockNode(layout?: PoetryLayout, align?: PoetryAlign, width?: number): PoetryBlockNode;
|
|
57
|
+
export declare function $createPoetryBlockNode(layout?: PoetryLayout, align?: PoetryAlign, width?: number, spacing?: PoetrySpacing): PoetryBlockNode;
|
|
51
58
|
export declare function $isPoetryBlockNode(node: LexicalNode | null | undefined): node is PoetryBlockNode;
|
|
52
59
|
//# sourceMappingURL=PoetryNode.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PoetryNode.d.ts","sourceRoot":"","sources":["../../src/blocks/PoetryNode.tsx"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,KAAK,qBAAqB,EAC1B,KAAK,MAAM,EACX,WAAW,EACZ,MAAM,SAAS,CAAC;AAEjB,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,YAAY,
|
|
1
|
+
{"version":3,"file":"PoetryNode.d.ts","sourceRoot":"","sources":["../../src/blocks/PoetryNode.tsx"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,KAAK,qBAAqB,EAC1B,KAAK,MAAM,EACX,WAAW,EACZ,MAAM,SAAS,CAAC;AAEjB,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,YAAY,CAAC;AACnD,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AACjE,iFAAiF;AACjF,eAAO,MAAM,eAAe,oDAAqD,CAAC;AAClF,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAC7D,eAAO,MAAM,sBAAsB,EAAE,aAAwB,CAAC;AAyB9D,MAAM,MAAM,yBAAyB,GAAG,MAAM,CAC5C;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,WAAW,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,aAAa,CAAA;CAAE,EACrF,qBAAqB,CACtB,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,qBAAa,eAAgB,SAAQ,WAAW;IAC9C,QAAQ,EAAE,YAAY,CAAC;IACvB,OAAO,EAAE,WAAW,CAAC;IACrB;8DAC0D;IAC1D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,aAAa,CAAC;gBAGvB,MAAM,GAAE,YAAuB,EAC/B,KAAK,GAAE,WAAuB,EAC9B,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,GAAE,aAAsC,EAC/C,GAAG,CAAC,EAAE,OAAO;IASf,MAAM,CAAC,OAAO,IAAI,MAAM;IAIxB,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,eAAe,GAAG,eAAe;IAIpD,SAAS,IAAI,YAAY;IAIzB,QAAQ,IAAI,WAAW;IAIvB,QAAQ,IAAI,MAAM,GAAG,SAAS;IAI9B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAMzC;;gEAE4D;IAC5D,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAM9C,UAAU,IAAI,aAAa;IAI3B,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAMxC,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAMlC,MAAM,CAAC,UAAU,CAAC,cAAc,EAAE,yBAAyB,GAAG,eAAe;IAI7E,UAAU,IAAI,yBAAyB;IAavC,MAAM,CAAC,SAAS,IAAI,gBAAgB,GAAG,IAAI;IAiB3C,SAAS,IAAI,eAAe;IAY5B,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW;IAa5C,SAAS,CAAC,QAAQ,EAAE,eAAe,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO;IAoBrF,UAAU,IAAI,KAAK;IAInB,YAAY,IAAI,OAAO;CAGxB;AAED,wBAAgB,sBAAsB,CACpC,MAAM,GAAE,YAAuB,EAC/B,KAAK,GAAE,WAAuB,EAC9B,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,GAAE,aAAsC,GAC9C,eAAe,CAEjB;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,IAAI,eAAe,CAEhG"}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { addClassNamesToElement } from '@lexical/utils';
|
|
2
2
|
import { $applyNodeReplacement, ElementNode, } from 'lexical';
|
|
3
|
-
|
|
3
|
+
/** Vertical space between couplets — an ordered scale the menu steps through. */
|
|
4
|
+
export const POETRY_SPACINGS = ['compact', 'normal', 'relaxed', 'loose'];
|
|
5
|
+
export const DEFAULT_POETRY_SPACING = 'normal';
|
|
6
|
+
const VALID_LAYOUTS = new Set(['single', 'two-column']);
|
|
4
7
|
const VALID_ALIGNS = new Set(['justify', 'left', 'right', 'start']);
|
|
8
|
+
const VALID_SPACINGS = new Set(POETRY_SPACINGS);
|
|
5
9
|
/** `text-align: justify` only stretches a line that actually wraps — a
|
|
6
10
|
* misra short enough to fit on one line would otherwise just sit at its own
|
|
7
11
|
* start edge instead of spreading its words across the full column width.
|
|
@@ -22,31 +26,31 @@ function applyWidthStyle(element, width) {
|
|
|
22
26
|
element.style.maxWidth = `${width}px`;
|
|
23
27
|
}
|
|
24
28
|
/**
|
|
25
|
-
* A poetry *section*: one or more couplets (two-line verse units)
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* restructured/grown. `layout`
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* in place of four fixed templates, per requirements doc §4.11.
|
|
29
|
+
* A poetry *section*: one or more couplets (two-line verse units) sharing
|
|
30
|
+
* one layout — single-column stacks each couplet's two misras directly as
|
|
31
|
+
* paragraph children (two per couplet, in order), two-column gives each
|
|
32
|
+
* couplet its own LayoutContainerNode row (built on the columns primitive,
|
|
33
|
+
* §4.9) — see blocks/poetryActions.ts's $getCouplets for how either shape
|
|
34
|
+
* is read, and $setPoetryLayout/$exitPoetryOnEnter for how children are
|
|
35
|
+
* restructured/grown between couplets and layouts. `layout` and `align`
|
|
36
|
+
* apply to the whole section, not per couplet; both mutate in place via
|
|
37
|
+
* poetryActions so converting a section between layouts doesn't lose
|
|
38
|
+
* selection/undo coherence. One extensible primitive in place of four
|
|
39
|
+
* fixed templates, per requirements doc §4.11.
|
|
37
40
|
*/
|
|
38
41
|
export class PoetryBlockNode extends ElementNode {
|
|
39
|
-
constructor(layout = 'single', align = 'justify', width, key) {
|
|
42
|
+
constructor(layout = 'single', align = 'justify', width, spacing = DEFAULT_POETRY_SPACING, key) {
|
|
40
43
|
super(key);
|
|
41
44
|
this.__layout = layout;
|
|
42
45
|
this.__align = align;
|
|
43
46
|
this.__width = width;
|
|
47
|
+
this.__spacing = spacing;
|
|
44
48
|
}
|
|
45
49
|
static getType() {
|
|
46
|
-
return 'poetry-
|
|
50
|
+
return 'poetry-couplet';
|
|
47
51
|
}
|
|
48
52
|
static clone(node) {
|
|
49
|
-
return new PoetryBlockNode(node.__layout, node.__align, node.__width, node.__key);
|
|
53
|
+
return new PoetryBlockNode(node.__layout, node.__align, node.__width, node.__spacing, node.__key);
|
|
50
54
|
}
|
|
51
55
|
getLayout() {
|
|
52
56
|
return this.getLatest().__layout;
|
|
@@ -70,22 +74,31 @@ export class PoetryBlockNode extends ElementNode {
|
|
|
70
74
|
writable.__layout = layout;
|
|
71
75
|
return writable;
|
|
72
76
|
}
|
|
77
|
+
getSpacing() {
|
|
78
|
+
return this.getLatest().__spacing;
|
|
79
|
+
}
|
|
80
|
+
setSpacing(spacing) {
|
|
81
|
+
const writable = this.getWritable();
|
|
82
|
+
writable.__spacing = spacing;
|
|
83
|
+
return writable;
|
|
84
|
+
}
|
|
73
85
|
setAlign(align) {
|
|
74
86
|
const writable = this.getWritable();
|
|
75
87
|
writable.__align = align;
|
|
76
88
|
return writable;
|
|
77
89
|
}
|
|
78
90
|
static importJSON(serializedNode) {
|
|
79
|
-
return $createPoetryBlockNode(serializedNode.layout, serializedNode.align, serializedNode.width);
|
|
91
|
+
return $createPoetryBlockNode(serializedNode.layout, serializedNode.align, serializedNode.width, serializedNode.spacing);
|
|
80
92
|
}
|
|
81
93
|
exportJSON() {
|
|
82
94
|
const width = this.getWidth();
|
|
83
95
|
return {
|
|
84
96
|
...super.exportJSON(),
|
|
85
|
-
type: 'poetry-
|
|
97
|
+
type: 'poetry-couplet',
|
|
86
98
|
version: 1,
|
|
87
99
|
layout: this.getLayout(),
|
|
88
100
|
align: this.getAlign(),
|
|
101
|
+
spacing: this.getSpacing(),
|
|
89
102
|
...(width !== undefined ? { width } : {}),
|
|
90
103
|
};
|
|
91
104
|
}
|
|
@@ -100,7 +113,9 @@ export class PoetryBlockNode extends ElementNode {
|
|
|
100
113
|
const align = VALID_ALIGNS.has(rawAlign) ? rawAlign : 'justify';
|
|
101
114
|
const rawWidth = Number(domNode.getAttribute('data-likhari-poetry-width'));
|
|
102
115
|
const width = Number.isFinite(rawWidth) && rawWidth > 0 ? rawWidth : undefined;
|
|
103
|
-
|
|
116
|
+
const rawSpacing = domNode.getAttribute('data-likhari-poetry-spacing');
|
|
117
|
+
const spacing = VALID_SPACINGS.has(rawSpacing) ? rawSpacing : DEFAULT_POETRY_SPACING;
|
|
118
|
+
return { conversion: () => ({ node: $createPoetryBlockNode(layout, align, width, spacing) }), priority: 2 };
|
|
104
119
|
},
|
|
105
120
|
};
|
|
106
121
|
}
|
|
@@ -108,6 +123,7 @@ export class PoetryBlockNode extends ElementNode {
|
|
|
108
123
|
const element = document.createElement('div');
|
|
109
124
|
element.setAttribute('data-likhari-poetry-layout', this.getLayout());
|
|
110
125
|
element.setAttribute('data-likhari-poetry-align', this.getAlign());
|
|
126
|
+
element.setAttribute('data-likhari-poetry-spacing', this.getSpacing());
|
|
111
127
|
const width = this.getWidth();
|
|
112
128
|
if (width !== undefined)
|
|
113
129
|
element.setAttribute('data-likhari-poetry-width', String(width));
|
|
@@ -118,7 +134,7 @@ export class PoetryBlockNode extends ElementNode {
|
|
|
118
134
|
createDOM(config) {
|
|
119
135
|
const element = document.createElement('div');
|
|
120
136
|
const base = config.theme.poetry ?? 'likhari-poetry';
|
|
121
|
-
addClassNamesToElement(element, base, `${base}--${this.__layout}`);
|
|
137
|
+
addClassNamesToElement(element, base, `${base}--${this.__layout}`, `${base}--spacing-${this.__spacing}`);
|
|
122
138
|
applyAlignStyle(element, this.__align);
|
|
123
139
|
applyWidthStyle(element, this.__width);
|
|
124
140
|
return element;
|
|
@@ -133,6 +149,11 @@ export class PoetryBlockNode extends ElementNode {
|
|
|
133
149
|
dom.classList.remove(`${base}--${prevNode.__layout}`);
|
|
134
150
|
dom.classList.add(`${base}--${this.__layout}`);
|
|
135
151
|
}
|
|
152
|
+
if (prevNode.__spacing !== this.__spacing) {
|
|
153
|
+
const base = config.theme.poetry ?? 'likhari-poetry';
|
|
154
|
+
dom.classList.remove(`${base}--spacing-${prevNode.__spacing}`);
|
|
155
|
+
dom.classList.add(`${base}--spacing-${this.__spacing}`);
|
|
156
|
+
}
|
|
136
157
|
if (prevNode.__align !== this.__align) {
|
|
137
158
|
applyAlignStyle(dom, this.__align);
|
|
138
159
|
}
|
|
@@ -148,8 +169,8 @@ export class PoetryBlockNode extends ElementNode {
|
|
|
148
169
|
return true;
|
|
149
170
|
}
|
|
150
171
|
}
|
|
151
|
-
export function $createPoetryBlockNode(layout = 'single', align = 'justify', width) {
|
|
152
|
-
return $applyNodeReplacement(new PoetryBlockNode(layout, align, width));
|
|
172
|
+
export function $createPoetryBlockNode(layout = 'single', align = 'justify', width, spacing = DEFAULT_POETRY_SPACING) {
|
|
173
|
+
return $applyNodeReplacement(new PoetryBlockNode(layout, align, width, spacing));
|
|
153
174
|
}
|
|
154
175
|
export function $isPoetryBlockNode(node) {
|
|
155
176
|
return node instanceof PoetryBlockNode;
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { type ParagraphNode } from 'lexical';
|
|
2
|
-
import { type PoetryAlign, type
|
|
2
|
+
import { type PoetryAlign, type PoetryBlockNode, type PoetryLayout } from './PoetryNode.js';
|
|
3
3
|
/** One couplet's two misra paragraphs, in order. */
|
|
4
4
|
export type Couplet = [ParagraphNode, ParagraphNode];
|
|
5
5
|
/**
|
|
6
|
-
* A poetry block
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* the one place that knows how to read either wrapper, so nothing else does.
|
|
6
|
+
* A poetry block is a *section* of one or more couplets sharing one layout
|
|
7
|
+
* (single-column stacks each couplet's two misras directly as paragraph
|
|
8
|
+
* children, two deep per couplet; two-column gives each couplet its own
|
|
9
|
+
* LayoutContainerNode row). This walks that structure and returns each
|
|
10
|
+
* couplet as a pair, in document order — the one place that knows how to
|
|
11
|
+
* read either shape, so nothing else needs to.
|
|
13
12
|
*/
|
|
14
13
|
export declare function $getCouplets(node: PoetryBlockNode): Couplet[];
|
|
15
14
|
/** Every misra in the block, flattened across all its couplets — for
|
|
@@ -19,33 +18,22 @@ export declare function $getMisraParagraphs(node: PoetryBlockNode): ParagraphNod
|
|
|
19
18
|
/** The PoetryBlockNode the current selection is inside, or null. */
|
|
20
19
|
export declare function $getPoetryBlockFromSelection(): PoetryBlockNode | null;
|
|
21
20
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* (and dropping any individual 'centered' override, which only applies to
|
|
28
|
-
* the non-two-column shape), so content, selection and undo history all
|
|
29
|
-
* survive the conversion. Switching between 'single' and 'alternating' is
|
|
30
|
-
* purely an attribute change (both use the same PoetryCoupletNode
|
|
31
|
-
* structure) — no restructuring needed.
|
|
21
|
+
* The explicit "Insert couplet above/below" menu actions — mirrors the
|
|
22
|
+
* table menu's "Insert row before/after". Targets the couplet the caret is
|
|
23
|
+
* currently in, falling back to the block's last couplet (so the toolbar's
|
|
24
|
+
* always-available insert button has somewhere sensible to act on even
|
|
25
|
+
* without a precise caret position).
|
|
32
26
|
*/
|
|
33
|
-
export declare function $
|
|
27
|
+
export declare function $insertCoupletRelativeToSelection(position: 'before' | 'after'): boolean;
|
|
34
28
|
/**
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* false when the selection isn't inside a couplet.
|
|
29
|
+
* Converts every couplet in the block between single-column (two stacked
|
|
30
|
+
* misras) and two-column (built on the columns primitive, §4.9) in place —
|
|
31
|
+
* pulls each couplet's two misra paragraphs out of whichever shape
|
|
32
|
+
* currently holds them and rebuilds the other shape around the same
|
|
33
|
+
* paragraph nodes, preserving couplet order, so content, selection and
|
|
34
|
+
* undo history all survive the conversion.
|
|
42
35
|
*/
|
|
43
|
-
export declare function $
|
|
44
|
-
/** Whether the couplet the selection is inside is currently centered —
|
|
45
|
-
* always false for a two-column couplet, since that override only applies
|
|
46
|
-
* to the PoetryCoupletNode shape. Null when the selection isn't inside a
|
|
47
|
-
* couplet at all (vs. inside one that just isn't centered). */
|
|
48
|
-
export declare function $getCoupletCenteredFromSelection(): boolean | null;
|
|
36
|
+
export declare function $setPoetryLayout(node: PoetryBlockNode, layout: PoetryLayout): void;
|
|
49
37
|
/** A block at the very end of the document would otherwise leave no
|
|
50
38
|
* editable block to click or arrow down into — appends one empty paragraph
|
|
51
39
|
* if the block doesn't already have a next sibling. Idempotent: once a
|
|
@@ -56,10 +44,13 @@ export declare function $getCoupletCenteredFromSelection(): boolean | null;
|
|
|
56
44
|
export declare function $ensureTrailingParagraph(node: PoetryBlockNode): void;
|
|
57
45
|
/**
|
|
58
46
|
* Inserts a poetry couplet at the caret. If the caret is already inside a
|
|
59
|
-
* poetry block,
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
47
|
+
* poetry block, inserts a new couplet right after the one the caret is in
|
|
48
|
+
* (same as the "Insert couplet below" menu action — table-row-insert
|
|
49
|
+
* semantics, in its existing layout: "one poetry block can contain one or
|
|
50
|
+
* more couplets, in one or two column layout", so a block's layout is
|
|
51
|
+
* fixed once it has couplets, not chosen per couplet) and focuses its first
|
|
52
|
+
* misra. Otherwise creates a new block (in `layout`/`align`) with one
|
|
53
|
+
* couplet, after the selection's top-level element.
|
|
63
54
|
*/
|
|
64
55
|
export declare function $insertPoetryCouplet(layout: PoetryLayout, align: PoetryAlign): boolean;
|
|
65
56
|
/** Removes the couplet the selection is inside. If it's the block's only
|
|
@@ -97,4 +88,7 @@ export declare function $deletePoetryOnBackspace(): boolean;
|
|
|
97
88
|
* next couplet's first misra.
|
|
98
89
|
*/
|
|
99
90
|
export declare function $exitPoetryOnEnter(): boolean;
|
|
91
|
+
/** Steps the caret's poetry block one notch looser (+1) or tighter (-1) on
|
|
92
|
+
* the couplet-spacing scale; clamps at either end. */
|
|
93
|
+
export declare function $adjustPoetrySpacing(step: 1 | -1): boolean;
|
|
100
94
|
//# sourceMappingURL=poetryActions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"poetryActions.d.ts","sourceRoot":"","sources":["../../src/blocks/poetryActions.ts"],"names":[],"mappings":"AACA,OAAO,EAA4F,KAAK,aAAa,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"poetryActions.d.ts","sourceRoot":"","sources":["../../src/blocks/poetryActions.ts"],"names":[],"mappings":"AACA,OAAO,EAA4F,KAAK,aAAa,EAAE,MAAM,SAAS,CAAC;AAEvI,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,YAAY,EAClB,MAAM,cAAc,CAAC;AAEtB,oDAAoD;AACpD,MAAM,MAAM,OAAO,GAAG,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;AAErD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,EAAE,CAgB7D;AAED;;6CAE6C;AAC7C,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,eAAe,GAAG,aAAa,EAAE,CAE1E;AAED,oEAAoE;AACpE,wBAAgB,4BAA4B,IAAI,eAAe,GAAG,IAAI,CAKrE;AA0DD;;;;;;GAMG;AACH,wBAAgB,iCAAiC,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,GAAG,OAAO,CAevF;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,eAAe,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI,CAmBlF;AAED;;;;;;qDAMqD;AACrD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CAEpE;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAiBtF;AAED;;;;wCAIwC;AACxC,wBAAgB,oBAAoB,IAAI,OAAO,CAwB9C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,IAAI,OAAO,CAqClD;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAgD5C;AAED;sDACsD;AACtD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO,CAO1D"}
|
|
@@ -1,32 +1,31 @@
|
|
|
1
1
|
import { $findMatchingParent } from '@lexical/utils';
|
|
2
2
|
import { $createParagraphNode, $getSelection, $isElementNode, $isParagraphNode, $isRangeSelection } from 'lexical';
|
|
3
3
|
import { $createLayoutContainerNode, $createLayoutItemNode, $isLayoutContainerNode, $isLayoutItemNode } from './LayoutNode.js';
|
|
4
|
-
import { $
|
|
5
|
-
import { $createPoetryBlockNode, $isPoetryBlockNode } from './PoetryNode.js';
|
|
4
|
+
import { $createPoetryBlockNode, $isPoetryBlockNode, POETRY_SPACINGS, } from './PoetryNode.js';
|
|
6
5
|
/**
|
|
7
|
-
* A poetry block
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* the one place that knows how to read either wrapper, so nothing else does.
|
|
6
|
+
* A poetry block is a *section* of one or more couplets sharing one layout
|
|
7
|
+
* (single-column stacks each couplet's two misras directly as paragraph
|
|
8
|
+
* children, two deep per couplet; two-column gives each couplet its own
|
|
9
|
+
* LayoutContainerNode row). This walks that structure and returns each
|
|
10
|
+
* couplet as a pair, in document order — the one place that knows how to
|
|
11
|
+
* read either shape, so nothing else needs to.
|
|
14
12
|
*/
|
|
15
13
|
export function $getCouplets(node) {
|
|
14
|
+
if (node.getLayout() === 'single') {
|
|
15
|
+
const paragraphs = node.getChildren().filter($isParagraphNode);
|
|
16
|
+
const couplets = [];
|
|
17
|
+
for (let i = 0; i + 1 < paragraphs.length; i += 2)
|
|
18
|
+
couplets.push([paragraphs[i], paragraphs[i + 1]]);
|
|
19
|
+
return couplets;
|
|
20
|
+
}
|
|
21
|
+
const containers = node.getChildren().filter($isLayoutContainerNode);
|
|
16
22
|
const couplets = [];
|
|
17
|
-
for (const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
else if ($isLayoutContainerNode(child)) {
|
|
24
|
-
const items = child.getChildren().filter($isLayoutItemNode);
|
|
25
|
-
const a = items[0]?.getFirstChild();
|
|
26
|
-
const b = items[1]?.getFirstChild();
|
|
27
|
-
if ($isParagraphNode(a) && $isParagraphNode(b))
|
|
28
|
-
couplets.push([a, b]);
|
|
29
|
-
}
|
|
23
|
+
for (const container of containers) {
|
|
24
|
+
const items = container.getChildren().filter($isLayoutItemNode);
|
|
25
|
+
const a = items[0]?.getFirstChild();
|
|
26
|
+
const b = items[1]?.getFirstChild();
|
|
27
|
+
if ($isParagraphNode(a) && $isParagraphNode(b))
|
|
28
|
+
couplets.push([a, b]);
|
|
30
29
|
}
|
|
31
30
|
return couplets;
|
|
32
31
|
}
|
|
@@ -56,53 +55,87 @@ function $findCoupletPosition(couplets, target) {
|
|
|
56
55
|
}
|
|
57
56
|
return null;
|
|
58
57
|
}
|
|
59
|
-
|
|
60
|
-
* every couplet has exactly one, so removing/replacing a couplet means
|
|
61
|
-
* operating on this, not on its misra paragraphs individually. */
|
|
62
|
-
function $findCoupletWrapper(misra) {
|
|
63
|
-
return $findMatchingParent(misra, (n) => $isPoetryCoupletNode(n) || $isLayoutContainerNode(n));
|
|
64
|
-
}
|
|
65
|
-
/** Appends a new couplet to the block, in its default layout (two-column
|
|
66
|
-
* for a 'two-column' block, a plain PoetryCoupletNode otherwise) unless
|
|
67
|
-
* `twoColumn` is given explicitly. */
|
|
68
|
-
function $appendCoupletTo(node, twoColumn) {
|
|
58
|
+
function $appendCoupletTo(node) {
|
|
69
59
|
const misraA = $createParagraphNode();
|
|
70
60
|
const misraB = $createParagraphNode();
|
|
71
|
-
|
|
72
|
-
|
|
61
|
+
if (node.getLayout() === 'single') {
|
|
62
|
+
node.append(misraA, misraB);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
73
65
|
const container = $createLayoutContainerNode('repeat(2, 1fr)');
|
|
74
66
|
container.append($createLayoutItemNode().append(misraA), $createLayoutItemNode().append(misraB));
|
|
75
67
|
node.append(container);
|
|
76
68
|
}
|
|
69
|
+
return [misraA, misraB];
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Inserts a new, empty couplet immediately before or after an existing one —
|
|
73
|
+
* the table-row-insert equivalent for a poetry block ("add/remove couplets
|
|
74
|
+
* just like adding/removing table rows"). `existingFirstMisra` is that
|
|
75
|
+
* couplet's first misra, used to locate its wrapper (nothing, in single
|
|
76
|
+
* layout — just its two sibling paragraphs; a LayoutContainerNode row in
|
|
77
|
+
* two-column) so the new couplet can be spliced in at the right spot
|
|
78
|
+
* regardless of layout.
|
|
79
|
+
*/
|
|
80
|
+
function $insertCoupletRelativeTo(existingFirstMisra, layout, position) {
|
|
81
|
+
const misraA = $createParagraphNode();
|
|
82
|
+
const misraB = $createParagraphNode();
|
|
83
|
+
if (layout === 'single') {
|
|
84
|
+
if (position === 'before') {
|
|
85
|
+
existingFirstMisra.insertBefore(misraA);
|
|
86
|
+
misraA.insertAfter(misraB);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
const existingSecondMisra = existingFirstMisra.getNextSibling() ?? existingFirstMisra;
|
|
90
|
+
existingSecondMisra.insertAfter(misraA);
|
|
91
|
+
misraA.insertAfter(misraB);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
77
94
|
else {
|
|
78
|
-
|
|
95
|
+
const container = $findMatchingParent(existingFirstMisra, $isLayoutContainerNode);
|
|
96
|
+
const newContainer = $createLayoutContainerNode('repeat(2, 1fr)');
|
|
97
|
+
newContainer.append($createLayoutItemNode().append(misraA), $createLayoutItemNode().append(misraB));
|
|
98
|
+
if (position === 'before')
|
|
99
|
+
container.insertBefore(newContainer);
|
|
100
|
+
else
|
|
101
|
+
container.insertAfter(newContainer);
|
|
79
102
|
}
|
|
80
103
|
return [misraA, misraB];
|
|
81
104
|
}
|
|
82
105
|
/**
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
106
|
+
* The explicit "Insert couplet above/below" menu actions — mirrors the
|
|
107
|
+
* table menu's "Insert row before/after". Targets the couplet the caret is
|
|
108
|
+
* currently in, falling back to the block's last couplet (so the toolbar's
|
|
109
|
+
* always-available insert button has somewhere sensible to act on even
|
|
110
|
+
* without a precise caret position).
|
|
111
|
+
*/
|
|
112
|
+
export function $insertCoupletRelativeToSelection(position) {
|
|
113
|
+
const block = $getPoetryBlockFromSelection();
|
|
114
|
+
if (!block)
|
|
115
|
+
return false;
|
|
116
|
+
const selection = $getSelection();
|
|
117
|
+
const couplets = $getCouplets(block);
|
|
118
|
+
const anchorNode = $isRangeSelection(selection) ? selection.anchor.getNode() : null;
|
|
119
|
+
const found = anchorNode ? $findCoupletPosition(couplets, anchorNode) : null;
|
|
120
|
+
const index = found ? found.coupletIndex : couplets.length - 1;
|
|
121
|
+
const target = couplets[index];
|
|
122
|
+
if (!target)
|
|
123
|
+
return false;
|
|
124
|
+
const [newA] = $insertCoupletRelativeTo(target[0], block.getLayout(), position);
|
|
125
|
+
newA.selectStart();
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Converts every couplet in the block between single-column (two stacked
|
|
130
|
+
* misras) and two-column (built on the columns primitive, §4.9) in place —
|
|
131
|
+
* pulls each couplet's two misra paragraphs out of whichever shape
|
|
132
|
+
* currently holds them and rebuilds the other shape around the same
|
|
133
|
+
* paragraph nodes, preserving couplet order, so content, selection and
|
|
134
|
+
* undo history all survive the conversion.
|
|
93
135
|
*/
|
|
94
136
|
export function $setPoetryLayout(node, layout) {
|
|
95
|
-
|
|
96
|
-
if (from === layout)
|
|
137
|
+
if (node.getLayout() === layout)
|
|
97
138
|
return;
|
|
98
|
-
const fromTwoColumn = from === 'two-column';
|
|
99
|
-
const toTwoColumn = layout === 'two-column';
|
|
100
|
-
if (fromTwoColumn === toTwoColumn) {
|
|
101
|
-
// Both 'single' and 'alternating' share the same PoetryCoupletNode
|
|
102
|
-
// structure — just relabel the block.
|
|
103
|
-
node.setLayoutAttribute(layout);
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
139
|
const couplets = $getCouplets(node);
|
|
107
140
|
for (const [a, b] of couplets) {
|
|
108
141
|
a.remove();
|
|
@@ -110,74 +143,19 @@ export function $setPoetryLayout(node, layout) {
|
|
|
110
143
|
}
|
|
111
144
|
for (const leftover of node.getChildren())
|
|
112
145
|
leftover.remove();
|
|
113
|
-
|
|
114
|
-
|
|
146
|
+
if (layout === 'single') {
|
|
147
|
+
for (const [a, b] of couplets)
|
|
148
|
+
node.append(a, b);
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
for (const [a, b] of couplets) {
|
|
115
152
|
const container = $createLayoutContainerNode('repeat(2, 1fr)');
|
|
116
153
|
container.append($createLayoutItemNode().append(a), $createLayoutItemNode().append(b));
|
|
117
154
|
node.append(container);
|
|
118
155
|
}
|
|
119
|
-
else {
|
|
120
|
-
node.append($createPoetryCoupletNode().append(a, b));
|
|
121
|
-
}
|
|
122
156
|
}
|
|
123
157
|
node.setLayoutAttribute(layout);
|
|
124
158
|
}
|
|
125
|
-
/**
|
|
126
|
-
* Sets whether the couplet the selection is inside renders as a narrower,
|
|
127
|
-
* centered box ("single, aligned centered") instead of the block's default
|
|
128
|
-
* width — independent of the block's own layout. A two-column couplet is
|
|
129
|
-
* converted into a PoetryCoupletNode first (its two columns stacked into
|
|
130
|
-
* two lines), since "centered" only applies to that shape; a couplet
|
|
131
|
-
* that's already a PoetryCoupletNode just has its flag flipped. Returns
|
|
132
|
-
* false when the selection isn't inside a couplet.
|
|
133
|
-
*/
|
|
134
|
-
export function $setCoupletCentered(centered) {
|
|
135
|
-
const block = $getPoetryBlockFromSelection();
|
|
136
|
-
if (!block)
|
|
137
|
-
return false;
|
|
138
|
-
const selection = $getSelection();
|
|
139
|
-
if (!$isRangeSelection(selection))
|
|
140
|
-
return false;
|
|
141
|
-
const couplets = $getCouplets(block);
|
|
142
|
-
const position = $findCoupletPosition(couplets, selection.anchor.getNode());
|
|
143
|
-
if (!position)
|
|
144
|
-
return false;
|
|
145
|
-
const [a, b] = couplets[position.coupletIndex];
|
|
146
|
-
const wrapper = $findCoupletWrapper(a);
|
|
147
|
-
if (!wrapper)
|
|
148
|
-
return false;
|
|
149
|
-
if ($isPoetryCoupletNode(wrapper)) {
|
|
150
|
-
wrapper.setCentered(centered);
|
|
151
|
-
return true;
|
|
152
|
-
}
|
|
153
|
-
// A two-column couplet: stack its two columns into a centered pair,
|
|
154
|
-
// replacing the LayoutContainerNode row with a PoetryCoupletNode in the
|
|
155
|
-
// same position.
|
|
156
|
-
a.remove();
|
|
157
|
-
b.remove();
|
|
158
|
-
const coupletNode = $createPoetryCoupletNode(centered).append(a, b);
|
|
159
|
-
wrapper.insertAfter(coupletNode);
|
|
160
|
-
wrapper.remove();
|
|
161
|
-
return true;
|
|
162
|
-
}
|
|
163
|
-
/** Whether the couplet the selection is inside is currently centered —
|
|
164
|
-
* always false for a two-column couplet, since that override only applies
|
|
165
|
-
* to the PoetryCoupletNode shape. Null when the selection isn't inside a
|
|
166
|
-
* couplet at all (vs. inside one that just isn't centered). */
|
|
167
|
-
export function $getCoupletCenteredFromSelection() {
|
|
168
|
-
const block = $getPoetryBlockFromSelection();
|
|
169
|
-
if (!block)
|
|
170
|
-
return null;
|
|
171
|
-
const selection = $getSelection();
|
|
172
|
-
if (!$isRangeSelection(selection))
|
|
173
|
-
return null;
|
|
174
|
-
const couplets = $getCouplets(block);
|
|
175
|
-
const position = $findCoupletPosition(couplets, selection.anchor.getNode());
|
|
176
|
-
if (!position)
|
|
177
|
-
return null;
|
|
178
|
-
const wrapper = $findCoupletWrapper(couplets[position.coupletIndex][0]);
|
|
179
|
-
return $isPoetryCoupletNode(wrapper) ? wrapper.getCentered() : false;
|
|
180
|
-
}
|
|
181
159
|
/** A block at the very end of the document would otherwise leave no
|
|
182
160
|
* editable block to click or arrow down into — appends one empty paragraph
|
|
183
161
|
* if the block doesn't already have a next sibling. Idempotent: once a
|
|
@@ -191,10 +169,13 @@ export function $ensureTrailingParagraph(node) {
|
|
|
191
169
|
}
|
|
192
170
|
/**
|
|
193
171
|
* Inserts a poetry couplet at the caret. If the caret is already inside a
|
|
194
|
-
* poetry block,
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
*
|
|
172
|
+
* poetry block, inserts a new couplet right after the one the caret is in
|
|
173
|
+
* (same as the "Insert couplet below" menu action — table-row-insert
|
|
174
|
+
* semantics, in its existing layout: "one poetry block can contain one or
|
|
175
|
+
* more couplets, in one or two column layout", so a block's layout is
|
|
176
|
+
* fixed once it has couplets, not chosen per couplet) and focuses its first
|
|
177
|
+
* misra. Otherwise creates a new block (in `layout`/`align`) with one
|
|
178
|
+
* couplet, after the selection's top-level element.
|
|
198
179
|
*/
|
|
199
180
|
export function $insertPoetryCouplet(layout, align) {
|
|
200
181
|
const selection = $getSelection();
|
|
@@ -202,13 +183,11 @@ export function $insertPoetryCouplet(layout, align) {
|
|
|
202
183
|
return false;
|
|
203
184
|
const existing = $getPoetryBlockFromSelection();
|
|
204
185
|
if (existing) {
|
|
205
|
-
|
|
206
|
-
misraA.selectStart();
|
|
207
|
-
return true;
|
|
186
|
+
return $insertCoupletRelativeToSelection('after');
|
|
208
187
|
}
|
|
209
188
|
const anchorTopLevel = selection.anchor.getNode().getTopLevelElementOrThrow();
|
|
210
189
|
const node = $createPoetryBlockNode(layout, align);
|
|
211
|
-
const [misraA] = $appendCoupletTo(node
|
|
190
|
+
const [misraA] = $appendCoupletTo(node);
|
|
212
191
|
anchorTopLevel.insertAfter(node);
|
|
213
192
|
$ensureTrailingParagraph(node);
|
|
214
193
|
misraA.selectStart();
|
|
@@ -234,7 +213,14 @@ export function $deletePoetryCouplet() {
|
|
|
234
213
|
block.remove();
|
|
235
214
|
return true;
|
|
236
215
|
}
|
|
237
|
-
|
|
216
|
+
const [a, b] = target;
|
|
217
|
+
const container = $findMatchingParent(a, $isLayoutContainerNode);
|
|
218
|
+
if (container)
|
|
219
|
+
container.remove();
|
|
220
|
+
else {
|
|
221
|
+
a.remove();
|
|
222
|
+
b.remove();
|
|
223
|
+
}
|
|
238
224
|
return true;
|
|
239
225
|
}
|
|
240
226
|
/**
|
|
@@ -260,11 +246,12 @@ export function $deletePoetryOnBackspace() {
|
|
|
260
246
|
const position = $findCoupletPosition(couplets, anchorNode);
|
|
261
247
|
if (!position || position.misraIndex !== 0)
|
|
262
248
|
return false;
|
|
263
|
-
const [
|
|
249
|
+
const [firstMisra] = couplets[position.coupletIndex];
|
|
264
250
|
const anchor = selection.anchor;
|
|
265
|
-
const isAtStart = anchor.key ===
|
|
251
|
+
const isAtStart = anchor.key === firstMisra.getKey() && anchor.offset === 0;
|
|
266
252
|
if (!isAtStart)
|
|
267
253
|
return false;
|
|
254
|
+
const [a, b] = couplets[position.coupletIndex];
|
|
268
255
|
if (!a.isEmpty() || !b.isEmpty())
|
|
269
256
|
return false;
|
|
270
257
|
if (couplets.length <= 1) {
|
|
@@ -274,7 +261,13 @@ export function $deletePoetryOnBackspace() {
|
|
|
274
261
|
previous.selectEnd();
|
|
275
262
|
return true;
|
|
276
263
|
}
|
|
277
|
-
$
|
|
264
|
+
const container = $findMatchingParent(a, $isLayoutContainerNode);
|
|
265
|
+
if (container)
|
|
266
|
+
container.remove();
|
|
267
|
+
else {
|
|
268
|
+
a.remove();
|
|
269
|
+
b.remove();
|
|
270
|
+
}
|
|
278
271
|
const remaining = $getCouplets(block);
|
|
279
272
|
const previousCouplet = remaining[position.coupletIndex - 1] ?? remaining[0];
|
|
280
273
|
previousCouplet?.[1].selectEnd();
|
|
@@ -315,8 +308,15 @@ export function $exitPoetryOnEnter() {
|
|
|
315
308
|
// Drop the couplet we ourselves auto-created on the previous Enter —
|
|
316
309
|
// unless it's the block's only couplet, in which case leave the
|
|
317
310
|
// section as the user's (empty) content rather than deleting it.
|
|
318
|
-
if (couplets.length > 1)
|
|
319
|
-
$
|
|
311
|
+
if (couplets.length > 1) {
|
|
312
|
+
const container = $findMatchingParent(a, $isLayoutContainerNode);
|
|
313
|
+
if (container)
|
|
314
|
+
container.remove();
|
|
315
|
+
else {
|
|
316
|
+
a.remove();
|
|
317
|
+
b.remove();
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
320
|
const existingNext = block.getNextSibling();
|
|
321
321
|
const paragraph = $isParagraphNode(existingNext) ? existingNext : $createParagraphNode();
|
|
322
322
|
if (paragraph !== existingNext)
|
|
@@ -336,3 +336,14 @@ export function $exitPoetryOnEnter() {
|
|
|
336
336
|
newA.selectStart();
|
|
337
337
|
return true;
|
|
338
338
|
}
|
|
339
|
+
/** Steps the caret's poetry block one notch looser (+1) or tighter (-1) on
|
|
340
|
+
* the couplet-spacing scale; clamps at either end. */
|
|
341
|
+
export function $adjustPoetrySpacing(step) {
|
|
342
|
+
const block = $getPoetryBlockFromSelection();
|
|
343
|
+
if (!block)
|
|
344
|
+
return false;
|
|
345
|
+
const index = POETRY_SPACINGS.indexOf(block.getSpacing());
|
|
346
|
+
const next = POETRY_SPACINGS[Math.min(POETRY_SPACINGS.length - 1, Math.max(0, index + step))];
|
|
347
|
+
block.setSpacing(next);
|
|
348
|
+
return true;
|
|
349
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../../src/components/Toolbar.tsx"],"names":[],"mappings":"AAuEA,OAAO,EAAgB,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEzE,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EAA6D,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAItG,OAAO,KAAK,EAAE,MAAM,EAAW,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../../src/components/Toolbar.tsx"],"names":[],"mappings":"AAuEA,OAAO,EAAgB,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEzE,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EAA6D,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAItG,OAAO,KAAK,EAAE,MAAM,EAAW,MAAM,iBAAiB,CAAC;AAsfvD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,2BAA2B,CAAC;IACpC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,sEAAsE;IACtE,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,wFAAwF;IACxF,SAAS,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IAC1B,oFAAoF;IACpF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kGAAkG;IAClG,MAAM,CAAC,EAAE,oBAAoB,CAAC;CAC/B;AAED,wBAAgB,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAkC,EAAE,SAAiB,EAAE,MAAa,EAAE,MAAM,EAAE,EAAE,YAAY,+BA+jCxJ"}
|
|
@@ -15,7 +15,7 @@ import { INSERT_PAGE_BREAK_COMMAND } from '../blocks/PageBreakNode.js';
|
|
|
15
15
|
import { INSERT_LAYOUT_COMMAND } from '../blocks/LayoutNode.js';
|
|
16
16
|
import { INSERT_FOOTNOTE_COMMAND } from '../blocks/FootnoteNode.js';
|
|
17
17
|
import { $isPoetryBlockNode } from '../blocks/PoetryNode.js';
|
|
18
|
-
import { $
|
|
18
|
+
import { $adjustPoetrySpacing, $deletePoetryCouplet, $getPoetryBlockFromSelection, $insertCoupletRelativeToSelection, $setPoetryLayout, } from '../blocks/poetryActions.js';
|
|
19
19
|
import { INSERT_POETRY_COUPLET_COMMAND } from '../plugins/PoetryPlugin.js';
|
|
20
20
|
import { TableDialog } from './TableDialog.js';
|
|
21
21
|
import { LayoutDialog } from './LayoutDialog.js';
|
|
@@ -29,7 +29,7 @@ import { CANVAS_FONT_DEFAULTS, DEFAULT_FONT_OPTIONS, FONT_SIZES_PX } from '../fo
|
|
|
29
29
|
import { setStyleProperty } from '../utils/style.js';
|
|
30
30
|
import { useStrings } from '../i18n/useStrings.js';
|
|
31
31
|
import { usePortalTarget } from '../PortalTargetContext.js';
|
|
32
|
-
import { IconAbc, IconAlignCenter, IconAlignJustified, IconAlignLeft, IconAlignRight, IconArrowBackUp, IconArrowForwardUp, IconBold, IconClearFormatting, IconDeviceFloppy, IconDots, IconHistory, IconExternalLink, IconFeather, IconH1, IconH2, IconH3, IconH4, IconH5, IconH6, IconIndentDecrease, IconIndentIncrease, IconItalic, IconLetterCase, IconLetterCaseLower, IconLetterCaseUpper, IconLink, IconLinkOff, IconList, IconListCheck, IconListNumbers, IconPageBreak, IconPencil, IconPhoto, IconPilcrow, IconQuote, IconSeparatorHorizontal, IconSparkles, IconStrikethrough, IconSubscript, IconSuperscript, IconArrowMergeBoth, IconArrowsSplit2, IconColumnInsertLeft, IconColumnInsertRight, IconColumnRemove, IconColumns,
|
|
32
|
+
import { IconAbc, IconAlignCenter, IconAlignJustified, IconAlignLeft, IconAlignRight, IconArrowBackUp, IconArrowForwardUp, IconBold, IconClearFormatting, IconDeviceFloppy, IconDots, IconHistory, IconExternalLink, IconFeather, IconH1, IconH2, IconH3, IconH4, IconH5, IconH6, IconIndentDecrease, IconIndentIncrease, IconItalic, IconLetterCase, IconLetterCaseLower, IconLetterCaseUpper, IconLink, IconLinkOff, IconList, IconListCheck, IconListNumbers, IconPageBreak, IconPencil, IconPhoto, IconPilcrow, IconQuote, IconSeparatorHorizontal, IconSparkles, IconStrikethrough, IconSubscript, IconSuperscript, IconArrowMergeBoth, IconArrowsSplit2, IconColumnInsertLeft, IconColumnInsertRight, IconColumnRemove, IconColumns, IconColumns1, IconColumns2, IconNumber1Small, IconRowInsertBottom, IconRowInsertTop, IconRowRemove, IconArrowsMaximize, IconArrowsMinimize, IconTable, IconTableMinus, IconTrash, IconTableOptions, IconTextSize, IconTypography, IconUnderline, IconWand, } from '@tabler/icons-react';
|
|
33
33
|
/** Sentinel for "no inline style": Lexical returns the default it is given when
|
|
34
34
|
* the selection has none, so this tells "unstyled" (show the canvas default)
|
|
35
35
|
* apart from "styled with a value the dropdown doesn't list" (show nothing). */
|
|
@@ -51,7 +51,6 @@ const INITIAL_STATE = {
|
|
|
51
51
|
inPoetry: false,
|
|
52
52
|
poetryLayout: 'single',
|
|
53
53
|
poetryAlign: 'justify',
|
|
54
|
-
coupletCentered: false,
|
|
55
54
|
canUndo: false,
|
|
56
55
|
canRedo: false,
|
|
57
56
|
};
|
|
@@ -163,13 +162,14 @@ function TableMenuItems({ strings, direction, rows, columns, canMergeCells, canU
|
|
|
163
162
|
};
|
|
164
163
|
return (_jsxs(_Fragment, { children: [_jsx(Menu.Label, { children: t.menuLabel }), item(IconRowInsertTop, manyRows ? t.insertRowsBefore : t.insertRowBefore, () => $insertTableRows(false)), item(IconRowInsertBottom, manyRows ? t.insertRowsAfter : t.insertRowAfter, () => $insertTableRows(true)), item(rtl ? IconColumnInsertRight : IconColumnInsertLeft, manyColumns ? t.insertColumnsBefore : t.insertColumnBefore, () => $insertTableColumns(false)), item(rtl ? IconColumnInsertLeft : IconColumnInsertRight, manyColumns ? t.insertColumnsAfter : t.insertColumnAfter, () => $insertTableColumns(true)), (canMergeCells || canUnmergeCell) && _jsx(Menu.Divider, {}), canMergeCells && item(IconArrowMergeBoth, t.mergeCells, $mergeTableCells), canUnmergeCell && item(IconArrowsSplit2, t.unmergeCell, $unmergeTableCell), _jsx(Menu.Divider, {}), item(IconRowRemove, manyRows ? t.deleteRows : t.deleteRow, $deleteTableRows), item(IconColumnRemove, manyColumns ? t.deleteColumns : t.deleteColumn, $deleteTableColumns), item(IconTableMinus, t.deleteTable, $deleteTable, 'red')] }));
|
|
165
164
|
}
|
|
166
|
-
/** The poetry couplet menu's contents —
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
|
|
165
|
+
/** The poetry couplet menu's contents — layout (single/two-column) and
|
|
166
|
+
* literal alignment, both per-instance overrides (requirements doc §4.11:
|
|
167
|
+
* "set per CoupletNode, not inherited from a document-wide setting"), plus
|
|
168
|
+
* table-row-style structural actions (insert a couplet above/below the one
|
|
169
|
+
* the caret is in, delete it) — a poetry block is "one object with multiple
|
|
170
|
+
* couplets, add/remove like table rows", so these mirror TableMenuItems'
|
|
171
|
+
* own insert-before/insert-after/delete-row actions. */
|
|
172
|
+
function PoetryMenuItems({ strings, alignIcons, layout, align, onAction, }) {
|
|
173
173
|
const t = strings.poetryMenu;
|
|
174
174
|
const a = strings.toolbar.alignOptions;
|
|
175
175
|
const item = (icon, label, action, active = false, color) => {
|
|
@@ -184,7 +184,7 @@ function PoetryMenuItems({ strings, alignIcons, layout, align, centered, onActio
|
|
|
184
184
|
const setAlign = (next) => () => {
|
|
185
185
|
$getPoetryBlockFromSelection()?.setAlign(next);
|
|
186
186
|
};
|
|
187
|
-
return (_jsxs(_Fragment, { children: [_jsx(Menu.Label, { children: t.menuLabel }), item(IconColumns1, t.singleColumn, setLayout('single'), layout === 'single'), item(IconColumns2, t.twoColumn, setLayout('two-column'), layout === 'two-column'),
|
|
187
|
+
return (_jsxs(_Fragment, { children: [_jsx(Menu.Label, { children: t.menuLabel }), item(IconColumns1, t.singleColumn, setLayout('single'), layout === 'single'), item(IconColumns2, t.twoColumn, setLayout('two-column'), layout === 'two-column'), _jsx(Menu.Divider, {}), item(alignIcons.justify ?? IconAlignJustified, a.justify, setAlign('justify'), align === 'justify'), item(alignIcons.start ?? IconAlignLeft, a.start, setAlign('start'), align === 'start'), item(IconAlignLeft, a.left, setAlign('left'), align === 'left'), item(IconAlignRight, a.right, setAlign('right'), align === 'right'), _jsx(Menu.Divider, {}), item(IconRowInsertTop, t.insertCoupletBefore, () => $insertCoupletRelativeToSelection('before')), item(IconRowInsertBottom, t.insertCoupletAfter, () => $insertCoupletRelativeToSelection('after')), item(IconArrowsMinimize, t.tighterSpacing, () => $adjustPoetrySpacing(-1)), item(IconArrowsMaximize, t.looserSpacing, () => $adjustPoetrySpacing(1)), item(IconTrash, t.deleteCouplet, $deletePoetryCouplet, false, 'red')] }));
|
|
188
188
|
}
|
|
189
189
|
export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAULT_FONT_OPTIONS, direction = 'ltr', locale = 'en', drafts }) {
|
|
190
190
|
const [editor] = useLexicalComposerContext();
|
|
@@ -210,16 +210,7 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
210
210
|
if ($isTableSelection(selection)) {
|
|
211
211
|
const { rows, columns } = $getTableSelectionSize();
|
|
212
212
|
const canMergeCells = $canMergeSelectedCells();
|
|
213
|
-
setState((s) => ({
|
|
214
|
-
...s,
|
|
215
|
-
inTable: true,
|
|
216
|
-
tableRows: rows,
|
|
217
|
-
tableColumns: columns,
|
|
218
|
-
canMergeCells,
|
|
219
|
-
canUnmergeCell: false,
|
|
220
|
-
inPoetry: false,
|
|
221
|
-
coupletCentered: false,
|
|
222
|
-
}));
|
|
213
|
+
setState((s) => ({ ...s, inTable: true, tableRows: rows, tableColumns: columns, canMergeCells, canUnmergeCell: false, inPoetry: false }));
|
|
223
214
|
return;
|
|
224
215
|
}
|
|
225
216
|
if (!$isRangeSelection(selection))
|
|
@@ -256,7 +247,6 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
256
247
|
const elementFormat = ($isElementNode(element) ? element.getFormatType() : 'start') || 'start';
|
|
257
248
|
const poetryLayout = poetryBlock?.getLayout();
|
|
258
249
|
const poetryAlign = poetryBlock?.getAlign();
|
|
259
|
-
const coupletCentered = $getCoupletCenteredFromSelection();
|
|
260
250
|
setState((s) => ({
|
|
261
251
|
...s,
|
|
262
252
|
blockType,
|
|
@@ -275,7 +265,6 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
275
265
|
inPoetry: poetryBlock !== null,
|
|
276
266
|
poetryLayout: poetryLayout ?? s.poetryLayout,
|
|
277
267
|
poetryAlign: poetryAlign ?? s.poetryAlign,
|
|
278
|
-
coupletCentered: coupletCentered ?? false,
|
|
279
268
|
}));
|
|
280
269
|
});
|
|
281
270
|
}, [editor]);
|
|
@@ -821,7 +810,7 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
821
810
|
}, onRemove: removeLink, strings: strings }) })] })) : (_jsx(ToolbarButton, { icon: IconLink, title: strings.toolbar.insertLink, onClick: openLinkDialog })) }, "link")),
|
|
822
811
|
showStubInsertGroup && (_jsxs("div", { className: "likhari-toolbar-group likhari-toolbar-group--collapse-tablet", children: [(config.images.linked || config.images.embedded) && (_jsx(ToolbarButton, { icon: IconPhoto, title: strings.toolbar.insertImage, onClick: openImageDialog })), config.blocks.pageBreak && (_jsx(ToolbarButton, { icon: IconPageBreak, title: strings.toolbar.insertPageBreak, onClick: () => editor.dispatchCommand(INSERT_PAGE_BREAK_COMMAND, undefined) })), config.tables && _jsx(ToolbarButton, { icon: IconTable, title: strings.toolbar.insertTable, onClick: openTableDialog }), config.columns && _jsx(ToolbarButton, { icon: IconColumns, title: strings.toolbar.insertColumns, onClick: openLayoutDialog }), config.footnotes && (_jsx(ToolbarButton, { icon: IconNumber1Small, title: strings.toolbar.insertFootnote, onClick: () => editor.dispatchCommand(INSERT_FOOTNOTE_COMMAND, undefined) })), config.blocks.horizontalRule && (_jsx(ToolbarButton, { icon: IconSeparatorHorizontal, title: strings.toolbar.insertHorizontalRule, onClick: () => editor.dispatchCommand(INSERT_HORIZONTAL_RULE_COMMAND, undefined) })), config.poetry.enabled && locale !== 'en' && (_jsx(ToolbarButton, { icon: IconFeather, title: strings.toolbar.insertPoetryCouplet, onClick: () => editor.dispatchCommand(INSERT_POETRY_COUPLET_COMMAND, { layout: config.poetry.defaultLayout, align: 'justify' }) }))] }, "stubInsert")),
|
|
823
812
|
config.tables && state.inTable && (_jsx("div", { className: "likhari-toolbar-group", children: _jsxs(Menu, { position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: 240, onOpen: snapshotSelection, children: [_jsx(Menu.Target, { children: _jsx("button", { type: "button", className: "likhari-toolbar-button", "data-active": "true", "aria-pressed": "true", "aria-haspopup": "menu", "aria-label": strings.toolbar.tableOptions, title: strings.toolbar.tableOptions, onMouseDown: (e) => e.preventDefault(), children: _jsx(IconTableOptions, { size: ICON_SIZE, stroke: ICON_STROKE }) }) }), _jsx(Menu.Dropdown, { children: _jsx(TableMenuItems, { strings: strings, direction: direction, rows: state.tableRows, columns: state.tableColumns, canMergeCells: state.canMergeCells, canUnmergeCell: state.canUnmergeCell, onAction: runMenuAction }) })] }) }, "tableActions")),
|
|
824
|
-
config.poetry.enabled && state.inPoetry && (_jsx("div", { className: "likhari-toolbar-group", children: _jsxs(Menu, { position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: 200, onOpen: snapshotSelection, children: [_jsx(Menu.Target, { children: _jsx("button", { type: "button", className: "likhari-toolbar-button", "data-active": "true", "aria-pressed": "true", "aria-haspopup": "menu", "aria-label": strings.toolbar.poetryOptions, title: strings.toolbar.poetryOptions, onMouseDown: (e) => e.preventDefault(), children: _jsx(IconFeather, { size: ICON_SIZE, stroke: ICON_STROKE }) }) }), _jsx(Menu.Dropdown, { children: _jsx(PoetryMenuItems, { strings: strings, alignIcons: ALIGN_ICONS, layout: state.poetryLayout, align: state.poetryAlign,
|
|
813
|
+
config.poetry.enabled && state.inPoetry && (_jsx("div", { className: "likhari-toolbar-group", children: _jsxs(Menu, { position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: 200, onOpen: snapshotSelection, children: [_jsx(Menu.Target, { children: _jsx("button", { type: "button", className: "likhari-toolbar-button", "data-active": "true", "aria-pressed": "true", "aria-haspopup": "menu", "aria-label": strings.toolbar.poetryOptions, title: strings.toolbar.poetryOptions, onMouseDown: (e) => e.preventDefault(), children: _jsx(IconFeather, { size: ICON_SIZE, stroke: ICON_STROKE }) }) }), _jsx(Menu.Dropdown, { children: _jsx(PoetryMenuItems, { strings: strings, alignIcons: ALIGN_ICONS, layout: state.poetryLayout, align: state.poetryAlign, onAction: runMenuAction }) })] }) }, "poetryActions")),
|
|
825
814
|
showLanguageGroup && (_jsxs("div", { className: "likhari-toolbar-group likhari-toolbar-group--collapse-tablet", children: [config.language.autocorrect && _jsx(StubButton, { icon: IconWand, title: strings.toolbar.autocorrect, comingSoon: strings.toolbar.comingSoon }), config.language.textCleanup && _jsx(StubButton, { icon: IconSparkles, title: strings.toolbar.textCleanup, comingSoon: strings.toolbar.comingSoon }), config.language.spellCheck && _jsx(StubButton, { icon: IconAbc, title: strings.toolbar.spellChecker, comingSoon: strings.toolbar.comingSoon })] }, "language")),
|
|
826
815
|
];
|
|
827
816
|
return (_jsxs("div", { className: "likhari-toolbar", role: "toolbar", "aria-label": strings.toolbar.ariaLabel, ref: toolbarContainerRef, children: [fixedGroups, movableGroups
|
|
@@ -840,7 +829,7 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
840
829
|
}, position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: 240, children: [_jsx(Menu.Target, { children: _jsx("span", { "aria-hidden": "true", style: { position: 'fixed', left: tableContext?.x ?? -9999, top: tableContext?.y ?? -9999, width: 1, height: 1, pointerEvents: 'none' } }) }), _jsx(Menu.Dropdown, { children: _jsx(TableMenuItems, { strings: strings, direction: direction, rows: tableContext?.rows ?? 1, columns: tableContext?.columns ?? 1, canMergeCells: state.canMergeCells, canUnmergeCell: state.canUnmergeCell, onAction: runMenuAction }) })] })), config.poetry.enabled && (_jsxs(Menu, { opened: poetryContext !== null, onChange: (opened) => {
|
|
841
830
|
if (!opened)
|
|
842
831
|
setPoetryContext(null);
|
|
843
|
-
}, position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: 200, children: [_jsx(Menu.Target, { children: _jsx("span", { "aria-hidden": "true", style: { position: 'fixed', left: poetryContext?.x ?? -9999, top: poetryContext?.y ?? -9999, width: 1, height: 1, pointerEvents: 'none' } }) }), _jsx(Menu.Dropdown, { children: _jsx(PoetryMenuItems, { strings: strings, alignIcons: ALIGN_ICONS, layout: state.poetryLayout, align: state.poetryAlign,
|
|
832
|
+
}, position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: 200, children: [_jsx(Menu.Target, { children: _jsx("span", { "aria-hidden": "true", style: { position: 'fixed', left: poetryContext?.x ?? -9999, top: poetryContext?.y ?? -9999, width: 1, height: 1, pointerEvents: 'none' } }) }), _jsx(Menu.Dropdown, { children: _jsx(PoetryMenuItems, { strings: strings, alignIcons: ALIGN_ICONS, layout: state.poetryLayout, align: state.poetryAlign, onAction: runMenuAction }) })] })), _jsxs("div", { "aria-hidden": "true", ref: toolbarMeasureRef, style: {
|
|
844
833
|
position: 'absolute',
|
|
845
834
|
visibility: 'hidden',
|
|
846
835
|
pointerEvents: 'none',
|
package/dist/i18n/strings.d.ts
CHANGED
|
@@ -142,9 +142,10 @@ export interface Strings {
|
|
|
142
142
|
menuLabel: string;
|
|
143
143
|
singleColumn: string;
|
|
144
144
|
twoColumn: string;
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
145
|
+
insertCoupletBefore: string;
|
|
146
|
+
insertCoupletAfter: string;
|
|
147
|
+
tighterSpacing: string;
|
|
148
|
+
looserSpacing: string;
|
|
148
149
|
deleteCouplet: string;
|
|
149
150
|
};
|
|
150
151
|
link: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"strings.d.ts","sourceRoot":"","sources":["../../src/i18n/strings.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"strings.d.ts","sourceRoot":"","sources":["../../src/i18n/strings.ts"],"names":[],"mappings":"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"}
|
package/dist/i18n/strings.js
CHANGED
|
@@ -125,9 +125,10 @@ const en = {
|
|
|
125
125
|
menuLabel: 'Poetry',
|
|
126
126
|
singleColumn: 'Single column',
|
|
127
127
|
twoColumn: 'Two column',
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
128
|
+
insertCoupletBefore: 'Insert couplet above',
|
|
129
|
+
insertCoupletAfter: 'Insert couplet below',
|
|
130
|
+
tighterSpacing: 'Tighter couplet spacing',
|
|
131
|
+
looserSpacing: 'Looser couplet spacing',
|
|
131
132
|
deleteCouplet: 'Delete couplet',
|
|
132
133
|
},
|
|
133
134
|
link: {
|
|
@@ -336,9 +337,10 @@ const ur = {
|
|
|
336
337
|
menuLabel: 'شاعری',
|
|
337
338
|
singleColumn: 'ایک کالم',
|
|
338
339
|
twoColumn: 'دو کالم',
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
340
|
+
insertCoupletBefore: 'اوپر شعر شامل کریں',
|
|
341
|
+
insertCoupletAfter: 'نیچے شعر شامل کریں',
|
|
342
|
+
tighterSpacing: 'شعروں کے درمیان کم جگہ',
|
|
343
|
+
looserSpacing: 'شعروں کے درمیان زیادہ جگہ',
|
|
342
344
|
deleteCouplet: 'شعر حذف کریں',
|
|
343
345
|
},
|
|
344
346
|
link: {
|
|
@@ -547,9 +549,10 @@ const paShahmukhi = {
|
|
|
547
549
|
menuLabel: 'شاعری',
|
|
548
550
|
singleColumn: 'اک کالم',
|
|
549
551
|
twoColumn: 'دو کالم',
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
552
|
+
insertCoupletBefore: 'اُتے شعر شامل کرو',
|
|
553
|
+
insertCoupletAfter: 'ھیٹھ شعر شامل کرو',
|
|
554
|
+
tighterSpacing: 'شعراں وچکار گھٹ جگہ',
|
|
555
|
+
looserSpacing: 'شعراں وچکار ودھ جگہ',
|
|
553
556
|
deleteCouplet: 'شعر مٹاؤ',
|
|
554
557
|
},
|
|
555
558
|
link: {
|
package/dist/nodes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nodes.d.ts","sourceRoot":"","sources":["../src/nodes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"nodes.d.ts","sourceRoot":"","sources":["../src/nodes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAalD;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,WAAW,CAAC,EAkB5C,CAAC"}
|
package/dist/nodes.js
CHANGED
|
@@ -9,7 +9,6 @@ import { LayoutContainerNode, LayoutItemNode } from './blocks/LayoutNode.js';
|
|
|
9
9
|
import { FootnoteReferenceNode } from './blocks/FootnoteNode.js';
|
|
10
10
|
import { FootnoteItemNode, FootnoteListNode } from './blocks/FootnoteListNode.js';
|
|
11
11
|
import { PoetryBlockNode } from './blocks/PoetryNode.js';
|
|
12
|
-
import { PoetryCoupletNode } from './blocks/PoetryCoupletNode.js';
|
|
13
12
|
/**
|
|
14
13
|
* Node types registered on the editor at construction time. Per
|
|
15
14
|
* editor-architecture-design.md §2, node registration cannot be conditional
|
|
@@ -37,5 +36,4 @@ export const EDITOR_NODES = [
|
|
|
37
36
|
FootnoteListNode,
|
|
38
37
|
FootnoteItemNode,
|
|
39
38
|
PoetryBlockNode,
|
|
40
|
-
PoetryCoupletNode,
|
|
41
39
|
];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PoetryPlugin.d.ts","sourceRoot":"","sources":["../../src/plugins/PoetryPlugin.tsx"],"names":[],"mappings":"AAEA,OAAO,EAML,KAAK,cAAc,EACpB,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"PoetryPlugin.d.ts","sourceRoot":"","sources":["../../src/plugins/PoetryPlugin.tsx"],"names":[],"mappings":"AAEA,OAAO,EAML,KAAK,cAAc,EACpB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAmB,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAG5F,eAAO,MAAM,6BAA6B,EAAE,cAAc,CAAC;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,WAAW,CAAA;CAAE,CAEtG,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,SA4C3B"}
|
|
@@ -3,7 +3,6 @@ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext
|
|
|
3
3
|
import { COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_HIGH, KEY_BACKSPACE_COMMAND, KEY_ENTER_COMMAND, createCommand, } from 'lexical';
|
|
4
4
|
import { mergeRegister } from '@lexical/utils';
|
|
5
5
|
import { LayoutContainerNode, LayoutItemNode } from '../blocks/LayoutNode.js';
|
|
6
|
-
import { PoetryCoupletNode } from '../blocks/PoetryCoupletNode.js';
|
|
7
6
|
import { PoetryBlockNode } from '../blocks/PoetryNode.js';
|
|
8
7
|
import { $deletePoetryOnBackspace, $ensureTrailingParagraph, $exitPoetryOnEnter, $insertPoetryCouplet } from '../blocks/poetryActions.js';
|
|
9
8
|
export const INSERT_POETRY_COUPLET_COMMAND = createCommand('INSERT_POETRY_COUPLET_COMMAND');
|
|
@@ -22,8 +21,8 @@ export const INSERT_POETRY_COUPLET_COMMAND = createCommand('INSERT_POETRY_COUPLE
|
|
|
22
21
|
export function PoetryPlugin() {
|
|
23
22
|
const [editor] = useLexicalComposerContext();
|
|
24
23
|
useEffect(() => {
|
|
25
|
-
if (!editor.hasNodes([PoetryBlockNode,
|
|
26
|
-
throw new Error('PoetryPlugin: PoetryBlockNode
|
|
24
|
+
if (!editor.hasNodes([PoetryBlockNode, LayoutContainerNode, LayoutItemNode])) {
|
|
25
|
+
throw new Error('PoetryPlugin: PoetryBlockNode (and the columns nodes it composes) not registered on the editor');
|
|
27
26
|
}
|
|
28
27
|
return mergeRegister(editor.registerCommand(INSERT_POETRY_COUPLET_COMMAND, ({ layout, align }) => $insertPoetryCouplet(layout, align), COMMAND_PRIORITY_EDITOR), editor.registerNodeTransform(PoetryBlockNode, (node) => {
|
|
29
28
|
if (node.getChildrenSize() === 0) {
|
package/dist/theme/editor.css
CHANGED
|
@@ -407,75 +407,56 @@
|
|
|
407
407
|
/* Misra lines sit tight against each other within a couplet — the generic
|
|
408
408
|
.likhari-paragraph margin would otherwise add the same gap between a
|
|
409
409
|
couplet's own two lines as between separate couplets within the same
|
|
410
|
-
block, losing the pairing entirely.
|
|
411
|
-
.likhari-poetry-couplet (single-column/alternating/centered) and
|
|
412
|
-
.likhari-layout-container (two-column) — one wrapper box per couplet,
|
|
413
|
-
regardless of type — so "extra space after every couplet" is just
|
|
414
|
-
margin-bottom on every non-last couplet of either kind. */
|
|
410
|
+
block, losing the pairing entirely. */
|
|
415
411
|
.likhari-poetry .likhari-paragraph {
|
|
416
412
|
margin: 0;
|
|
417
413
|
}
|
|
418
414
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
415
|
+
/* A poetry block is "one object with multiple couplets, add/remove like
|
|
416
|
+
table rows" — so couplet boundaries get the same visible divider as a
|
|
417
|
+
table's internal row borders, not just extra space. Every couplet but
|
|
418
|
+
the first (nth-child(odd), since each couplet is two paragraph
|
|
419
|
+
children — its first misra always lands on an odd position) gets a
|
|
420
|
+
border-top in place of the previous couplet's margin-bottom. */
|
|
421
|
+
.likhari-poetry--single .likhari-paragraph:nth-child(odd):not(:first-child) {
|
|
422
|
+
border-top: 1px dashed var(--editor-line-strong);
|
|
423
|
+
margin-top: var(--poetry-couplet-gap);
|
|
424
|
+
padding-top: calc(var(--poetry-couplet-gap) * 0.6);
|
|
422
425
|
}
|
|
423
426
|
|
|
424
|
-
.likhari-poetry-couplet
|
|
425
|
-
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
/* "Two columns with a couplet that is single, aligned centered": a couplet
|
|
429
|
-
can individually override to a narrower, page-centered box regardless of
|
|
430
|
-
the block's own layout — the same capped-width + auto-margin centering
|
|
431
|
-
.likhari-poetry itself uses, scoped to just this one couplet. */
|
|
432
|
-
.likhari-poetry-couplet--centered {
|
|
433
|
-
width: fit-content;
|
|
434
|
-
max-width: 70%;
|
|
435
|
-
margin-inline: auto;
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
/* "Aligned alternative": every couplet is the same fixed width, but
|
|
439
|
-
consecutive couplets alternate which edge they're pinned to — since both
|
|
440
|
-
widths overlap past the midpoint, the couplets visually stagger with
|
|
441
|
-
some overlap toward the center, rather than all stacking flush to one
|
|
442
|
-
side or centered identically. */
|
|
443
|
-
.likhari-poetry--alternating .likhari-poetry-couplet {
|
|
444
|
-
width: 65%;
|
|
445
|
-
max-width: none;
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
.likhari-poetry--alternating .likhari-poetry-couplet:nth-of-type(odd) {
|
|
449
|
-
margin-inline-end: auto;
|
|
450
|
-
}
|
|
427
|
+
.likhari-poetry--spacing-compact { --poetry-couplet-gap: 0.4em; }
|
|
428
|
+
.likhari-poetry--spacing-normal { --poetry-couplet-gap: 1em; }
|
|
429
|
+
.likhari-poetry--spacing-relaxed { --poetry-couplet-gap: 1.8em; }
|
|
430
|
+
.likhari-poetry--spacing-loose { --poetry-couplet-gap: 2.8em; }
|
|
451
431
|
|
|
452
|
-
.likhari-poetry--
|
|
453
|
-
margin-inline-start: auto;
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
/* Only inside a poetry block's own two-column couplets: no block margin
|
|
457
|
-
(the generic .likhari-layout-container rule's margin is for a
|
|
458
|
-
stand-alone Columns insert, not one couplet of several in a poetry
|
|
459
|
-
block — spacing between couplets is the margin-bottom rule above
|
|
460
|
-
instead) and no grid gap — the divider below sits exactly on the track
|
|
461
|
-
boundary, so spacing instead comes from matching padding on each side
|
|
462
|
-
of it, which keeps the gutter visually even on both sides of the line. */
|
|
463
|
-
.likhari-poetry > .likhari-layout-container {
|
|
432
|
+
.likhari-poetry--two-column .likhari-layout-container {
|
|
464
433
|
margin: 0;
|
|
434
|
+
/* No grid gap — the column divider sits exactly on the track boundary,
|
|
435
|
+
so spacing instead comes from matching padding on each side of it,
|
|
436
|
+
which keeps the gutter visually even on both sides of the line. */
|
|
465
437
|
gap: 0;
|
|
466
438
|
}
|
|
467
439
|
|
|
468
|
-
|
|
440
|
+
/* One row per couplet in two-column layout — same table-row-border
|
|
441
|
+
treatment as the single-column rule above, between couplets instead of
|
|
442
|
+
within one. */
|
|
443
|
+
.likhari-poetry--two-column .likhari-layout-container:not(:first-child) {
|
|
444
|
+
border-top: 1px dashed var(--editor-line-strong);
|
|
445
|
+
margin-top: var(--poetry-couplet-gap);
|
|
446
|
+
padding-top: calc(var(--poetry-couplet-gap) * 0.6);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
.likhari-poetry--two-column .likhari-layout-item {
|
|
469
450
|
text-align: inherit;
|
|
470
451
|
}
|
|
471
452
|
|
|
472
|
-
.likhari-poetry .likhari-layout-item:first-child {
|
|
453
|
+
.likhari-poetry--two-column .likhari-layout-item:first-child {
|
|
473
454
|
padding-inline-end: 20px;
|
|
474
455
|
}
|
|
475
456
|
|
|
476
457
|
/* A visible divider between misra columns, same dashed language as the
|
|
477
458
|
couplet's own border — matches a table's internal cell borders. */
|
|
478
|
-
.likhari-poetry .likhari-layout-item:not(:first-child) {
|
|
459
|
+
.likhari-poetry--two-column .likhari-layout-item:not(:first-child) {
|
|
479
460
|
border-inline-start: 1px dashed var(--editor-line-strong);
|
|
480
461
|
padding-inline-start: 20px;
|
|
481
462
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editorTheme.d.ts","sourceRoot":"","sources":["../../src/theme/editorTheme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"editorTheme.d.ts","sourceRoot":"","sources":["../../src/theme/editorTheme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,kBAgDzB,CAAC"}
|
|
@@ -46,7 +46,6 @@ export const editorTheme = {
|
|
|
46
46
|
footnoteList: 'likhari-footnote-list',
|
|
47
47
|
footnoteItem: 'likhari-footnote-item',
|
|
48
48
|
poetry: 'likhari-poetry',
|
|
49
|
-
poetryCouplet: 'likhari-poetry-couplet',
|
|
50
49
|
table: 'likhari-table',
|
|
51
50
|
tableRow: 'likhari-table-row',
|
|
52
51
|
tableCell: 'likhari-table-cell',
|
package/package.json
CHANGED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { type DOMConversionMap, type DOMExportOutput, type EditorConfig, type LexicalNode, type NodeKey, type SerializedElementNode, type Spread, ElementNode } from 'lexical';
|
|
2
|
-
export type SerializedPoetryCoupletNode = Spread<{
|
|
3
|
-
centered: boolean;
|
|
4
|
-
}, SerializedElementNode>;
|
|
5
|
-
/**
|
|
6
|
-
* One couplet's two misra lines, wrapped so each couplet can carry its own
|
|
7
|
-
* rendering override independent of its PoetryBlockNode's overall layout —
|
|
8
|
-
* currently just `centered` (a narrower box, centered on the page, instead
|
|
9
|
-
* of the block's default width): "two columns with a couplet that is
|
|
10
|
-
* single, aligned centered" mixes LayoutContainerNode rows (two-column
|
|
11
|
-
* couplets) with centered PoetryCoupletNodes in the same block, each
|
|
12
|
-
* couplet choosing independently.
|
|
13
|
-
*
|
|
14
|
-
* Used for single-column and alternating block layouts; a two-column
|
|
15
|
-
* couplet uses LayoutContainerNode instead (its own two-item row already
|
|
16
|
-
* gives it a natural per-couplet box, so it doesn't need this wrapper).
|
|
17
|
-
*/
|
|
18
|
-
export declare class PoetryCoupletNode extends ElementNode {
|
|
19
|
-
__centered: boolean;
|
|
20
|
-
constructor(centered?: boolean, key?: NodeKey);
|
|
21
|
-
static getType(): string;
|
|
22
|
-
static clone(node: PoetryCoupletNode): PoetryCoupletNode;
|
|
23
|
-
getCentered(): boolean;
|
|
24
|
-
setCentered(centered: boolean): this;
|
|
25
|
-
static importJSON(serializedNode: SerializedPoetryCoupletNode): PoetryCoupletNode;
|
|
26
|
-
exportJSON(): SerializedPoetryCoupletNode;
|
|
27
|
-
static importDOM(): DOMConversionMap | null;
|
|
28
|
-
exportDOM(): DOMExportOutput;
|
|
29
|
-
createDOM(config: EditorConfig): HTMLElement;
|
|
30
|
-
updateDOM(prevNode: PoetryCoupletNode, dom: HTMLElement, config: EditorConfig): boolean;
|
|
31
|
-
canBeEmpty(): false;
|
|
32
|
-
canIndent(): false;
|
|
33
|
-
}
|
|
34
|
-
export declare function $createPoetryCoupletNode(centered?: boolean): PoetryCoupletNode;
|
|
35
|
-
export declare function $isPoetryCoupletNode(node: LexicalNode | null | undefined): node is PoetryCoupletNode;
|
|
36
|
-
//# sourceMappingURL=PoetryCoupletNode.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PoetryCoupletNode.d.ts","sourceRoot":"","sources":["../../src/blocks/PoetryCoupletNode.tsx"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,KAAK,qBAAqB,EAC1B,KAAK,MAAM,EACX,WAAW,EACZ,MAAM,SAAS,CAAC;AAEjB,MAAM,MAAM,2BAA2B,GAAG,MAAM,CAAC;IAAE,QAAQ,EAAE,OAAO,CAAA;CAAE,EAAE,qBAAqB,CAAC,CAAC;AAE/F;;;;;;;;;;;;GAYG;AACH,qBAAa,iBAAkB,SAAQ,WAAW;IAChD,UAAU,EAAE,OAAO,CAAC;gBAER,QAAQ,UAAQ,EAAE,GAAG,CAAC,EAAE,OAAO;IAK3C,MAAM,CAAC,OAAO,IAAI,MAAM;IAIxB,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,iBAAiB,GAAG,iBAAiB;IAIxD,WAAW,IAAI,OAAO;IAItB,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;IAMpC,MAAM,CAAC,UAAU,CAAC,cAAc,EAAE,2BAA2B,GAAG,iBAAiB;IAIjF,UAAU,IAAI,2BAA2B;IAIzC,MAAM,CAAC,SAAS,IAAI,gBAAgB,GAAG,IAAI;IAU3C,SAAS,IAAI,eAAe;IAO5B,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW;IAQ5C,SAAS,CAAC,QAAQ,EAAE,iBAAiB,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO;IAQvF,UAAU,IAAI,KAAK;IAInB,SAAS,IAAI,KAAK;CAGnB;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,UAAQ,GAAG,iBAAiB,CAE5E;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,IAAI,iBAAiB,CAEpG"}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { addClassNamesToElement } from '@lexical/utils';
|
|
2
|
-
import { $applyNodeReplacement, ElementNode, } from 'lexical';
|
|
3
|
-
/**
|
|
4
|
-
* One couplet's two misra lines, wrapped so each couplet can carry its own
|
|
5
|
-
* rendering override independent of its PoetryBlockNode's overall layout —
|
|
6
|
-
* currently just `centered` (a narrower box, centered on the page, instead
|
|
7
|
-
* of the block's default width): "two columns with a couplet that is
|
|
8
|
-
* single, aligned centered" mixes LayoutContainerNode rows (two-column
|
|
9
|
-
* couplets) with centered PoetryCoupletNodes in the same block, each
|
|
10
|
-
* couplet choosing independently.
|
|
11
|
-
*
|
|
12
|
-
* Used for single-column and alternating block layouts; a two-column
|
|
13
|
-
* couplet uses LayoutContainerNode instead (its own two-item row already
|
|
14
|
-
* gives it a natural per-couplet box, so it doesn't need this wrapper).
|
|
15
|
-
*/
|
|
16
|
-
export class PoetryCoupletNode extends ElementNode {
|
|
17
|
-
constructor(centered = false, key) {
|
|
18
|
-
super(key);
|
|
19
|
-
this.__centered = centered;
|
|
20
|
-
}
|
|
21
|
-
static getType() {
|
|
22
|
-
return 'poetry-couplet';
|
|
23
|
-
}
|
|
24
|
-
static clone(node) {
|
|
25
|
-
return new PoetryCoupletNode(node.__centered, node.__key);
|
|
26
|
-
}
|
|
27
|
-
getCentered() {
|
|
28
|
-
return this.getLatest().__centered;
|
|
29
|
-
}
|
|
30
|
-
setCentered(centered) {
|
|
31
|
-
const writable = this.getWritable();
|
|
32
|
-
writable.__centered = centered;
|
|
33
|
-
return writable;
|
|
34
|
-
}
|
|
35
|
-
static importJSON(serializedNode) {
|
|
36
|
-
return $createPoetryCoupletNode(serializedNode.centered);
|
|
37
|
-
}
|
|
38
|
-
exportJSON() {
|
|
39
|
-
return { ...super.exportJSON(), type: 'poetry-couplet', version: 1, centered: this.getCentered() };
|
|
40
|
-
}
|
|
41
|
-
static importDOM() {
|
|
42
|
-
return {
|
|
43
|
-
div: (domNode) => {
|
|
44
|
-
if (!domNode.hasAttribute('data-likhari-poetry-couplet'))
|
|
45
|
-
return null;
|
|
46
|
-
const centered = domNode.getAttribute('data-likhari-poetry-couplet-centered') === 'true';
|
|
47
|
-
return { conversion: () => ({ node: $createPoetryCoupletNode(centered) }), priority: 2 };
|
|
48
|
-
},
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
exportDOM() {
|
|
52
|
-
const element = document.createElement('div');
|
|
53
|
-
element.setAttribute('data-likhari-poetry-couplet', '');
|
|
54
|
-
if (this.getCentered())
|
|
55
|
-
element.setAttribute('data-likhari-poetry-couplet-centered', 'true');
|
|
56
|
-
return { element };
|
|
57
|
-
}
|
|
58
|
-
createDOM(config) {
|
|
59
|
-
const element = document.createElement('div');
|
|
60
|
-
const base = config.theme.poetryCouplet ?? 'likhari-poetry-couplet';
|
|
61
|
-
addClassNamesToElement(element, base);
|
|
62
|
-
if (this.__centered)
|
|
63
|
-
element.classList.add(`${base}--centered`);
|
|
64
|
-
return element;
|
|
65
|
-
}
|
|
66
|
-
updateDOM(prevNode, dom, config) {
|
|
67
|
-
if (prevNode.__centered !== this.__centered) {
|
|
68
|
-
const base = config.theme.poetryCouplet ?? 'likhari-poetry-couplet';
|
|
69
|
-
dom.classList.toggle(`${base}--centered`, this.__centered);
|
|
70
|
-
}
|
|
71
|
-
return false;
|
|
72
|
-
}
|
|
73
|
-
canBeEmpty() {
|
|
74
|
-
return false;
|
|
75
|
-
}
|
|
76
|
-
canIndent() {
|
|
77
|
-
return false;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
export function $createPoetryCoupletNode(centered = false) {
|
|
81
|
-
return $applyNodeReplacement(new PoetryCoupletNode(centered));
|
|
82
|
-
}
|
|
83
|
-
export function $isPoetryCoupletNode(node) {
|
|
84
|
-
return node instanceof PoetryCoupletNode;
|
|
85
|
-
}
|