1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 | export function upcastStyleToAttribute(conversion, options) {
|
15 | const { modelAttribute, styleName, viewElement, defaultValue, reduceBoxSides = false, shouldUpcast = () => true } = options;
|
16 | conversion.for('upcast').attributeToAttribute({
|
17 | view: {
|
18 | name: viewElement,
|
19 | styles: {
|
20 | [styleName]: /[\s\S]+/
|
21 | }
|
22 | },
|
23 | model: {
|
24 | key: modelAttribute,
|
25 | value: (viewElement) => {
|
26 | if (!shouldUpcast(viewElement)) {
|
27 | return;
|
28 | }
|
29 | const normalized = viewElement.getNormalizedStyle(styleName);
|
30 | const value = reduceBoxSides ? reduceBoxSidesValue(normalized) : normalized;
|
31 | if (defaultValue !== value) {
|
32 | return value;
|
33 | }
|
34 | }
|
35 | }
|
36 | });
|
37 | }
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 | export function upcastBorderStyles(conversion, viewElementName, modelAttributes, defaultBorder) {
|
47 | conversion.for('upcast').add(dispatcher => dispatcher.on('element:' + viewElementName, (evt, data, conversionApi) => {
|
48 |
|
49 |
|
50 | if (!data.modelRange) {
|
51 | return;
|
52 | }
|
53 |
|
54 |
|
55 | const stylesToConsume = [
|
56 | 'border-top-width',
|
57 | 'border-top-color',
|
58 | 'border-top-style',
|
59 | 'border-bottom-width',
|
60 | 'border-bottom-color',
|
61 | 'border-bottom-style',
|
62 | 'border-right-width',
|
63 | 'border-right-color',
|
64 | 'border-right-style',
|
65 | 'border-left-width',
|
66 | 'border-left-color',
|
67 | 'border-left-style'
|
68 | ].filter(styleName => data.viewItem.hasStyle(styleName));
|
69 | if (!stylesToConsume.length) {
|
70 | return;
|
71 | }
|
72 | const matcherPattern = {
|
73 | styles: stylesToConsume
|
74 | };
|
75 |
|
76 | if (!conversionApi.consumable.test(data.viewItem, matcherPattern)) {
|
77 | return;
|
78 | }
|
79 | const modelElement = [...data.modelRange.getItems({ shallow: true })].pop();
|
80 | conversionApi.consumable.consume(data.viewItem, matcherPattern);
|
81 | const normalizedBorder = {
|
82 | style: data.viewItem.getNormalizedStyle('border-style'),
|
83 | color: data.viewItem.getNormalizedStyle('border-color'),
|
84 | width: data.viewItem.getNormalizedStyle('border-width')
|
85 | };
|
86 | const reducedBorder = {
|
87 | style: reduceBoxSidesValue(normalizedBorder.style),
|
88 | color: reduceBoxSidesValue(normalizedBorder.color),
|
89 | width: reduceBoxSidesValue(normalizedBorder.width)
|
90 | };
|
91 | if (reducedBorder.style !== defaultBorder.style) {
|
92 | conversionApi.writer.setAttribute(modelAttributes.style, reducedBorder.style, modelElement);
|
93 | }
|
94 | if (reducedBorder.color !== defaultBorder.color) {
|
95 | conversionApi.writer.setAttribute(modelAttributes.color, reducedBorder.color, modelElement);
|
96 | }
|
97 | if (reducedBorder.width !== defaultBorder.width) {
|
98 | conversionApi.writer.setAttribute(modelAttributes.width, reducedBorder.width, modelElement);
|
99 | }
|
100 | }));
|
101 | }
|
102 |
|
103 |
|
104 |
|
105 | export function downcastAttributeToStyle(conversion, options) {
|
106 | const { modelElement, modelAttribute, styleName } = options;
|
107 | conversion.for('downcast').attributeToAttribute({
|
108 | model: {
|
109 | name: modelElement,
|
110 | key: modelAttribute
|
111 | },
|
112 | view: modelAttributeValue => ({
|
113 | key: 'style',
|
114 | value: {
|
115 | [styleName]: modelAttributeValue
|
116 | }
|
117 | })
|
118 | });
|
119 | }
|
120 |
|
121 |
|
122 |
|
123 | export function downcastTableAttribute(conversion, options) {
|
124 | const { modelAttribute, styleName } = options;
|
125 | conversion.for('downcast').add(dispatcher => dispatcher.on(`attribute:${modelAttribute}:table`, (evt, data, conversionApi) => {
|
126 | const { item, attributeNewValue } = data;
|
127 | const { mapper, writer } = conversionApi;
|
128 | if (!conversionApi.consumable.consume(data.item, evt.name)) {
|
129 | return;
|
130 | }
|
131 | const table = [...mapper.toViewElement(item).getChildren()].find(child => child.is('element', 'table'));
|
132 | if (attributeNewValue) {
|
133 | writer.setStyle(styleName, attributeNewValue, table);
|
134 | }
|
135 | else {
|
136 | writer.removeStyle(styleName, table);
|
137 | }
|
138 | }));
|
139 | }
|
140 |
|
141 |
|
142 |
|
143 |
|
144 | function reduceBoxSidesValue(style) {
|
145 | if (!style) {
|
146 | return;
|
147 | }
|
148 | const sides = ['top', 'right', 'bottom', 'left'];
|
149 | const allSidesDefined = sides.every(side => style[side]);
|
150 | if (!allSidesDefined) {
|
151 | return style;
|
152 | }
|
153 | const topSideStyle = style.top;
|
154 | const allSidesEqual = sides.every(side => style[side] === topSideStyle);
|
155 | if (!allSidesEqual) {
|
156 | return style;
|
157 | }
|
158 | return topSideStyle;
|
159 | }
|