• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ckeditor / ckeditor5 / bedc2790-b778-4c70-b6fe-562bee0edacd

26 Nov 2024 07:50AM UTC coverage: 100.0%. Remained the same
bedc2790-b778-4c70-b6fe-562bee0edacd

push

circleci

web-flow
Merge pull request #17513 from ckeditor/cc/6747

Internal: Using existing license in the ckeditor5 root while preparing zip release.

14364 of 14364 branches covered (100.0%)

Branch coverage included in aggregate %.

38246 of 38246 relevant lines covered (100.0%)

9928.19 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

100.0
/packages/ckeditor5-alignment/src/alignmentediting.ts
1
/**
2
 * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
 * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
 */
5

6
/**
7
 * @module alignment/alignmentediting
8
 */
9

10
import { Plugin, type Editor } from 'ckeditor5/src/core.js';
11
import type { AttributeDescriptor } from 'ckeditor5/src/engine.js';
12

13
import AlignmentCommand from './alignmentcommand.js';
14
import { isDefault, isSupported, normalizeAlignmentOptions, supportedOptions } from './utils.js';
15
import type { AlignmentFormat, SupportedOption } from './alignmentconfig.js';
16

17
/**
18
 * The alignment editing feature. It introduces the {@link module:alignment/alignmentcommand~AlignmentCommand command} and adds
19
 * the `alignment` attribute for block elements in the {@link module:engine/model/model~Model model}.
20
 */
21
export default class AlignmentEditing extends Plugin {
22
        /**
23
         * @inheritDoc
24
         */
25
        public static get pluginName() {
26
                return 'AlignmentEditing' as const;
529✔
27
        }
28

29
        /**
30
         * @inheritDoc
31
         */
32
        public static override get isOfficialPlugin(): true {
33
                return true;
1✔
34
        }
35

36
        /**
37
         * @inheritDoc
38
         */
39
        constructor( editor: Editor ) {
40
                super( editor );
132✔
41

42
                editor.config.define( 'alignment', {
132✔
43
                        options: supportedOptions.map( option => ( { name: option } ) )
528✔
44
                } );
45
        }
46

47
        /**
48
         * @inheritDoc
49
         */
50
        public init(): void {
51
                const editor = this.editor;
132✔
52
                const locale = editor.locale;
132✔
53
                const schema = editor.model.schema;
132✔
54

55
                const options: Array<AlignmentFormat> = normalizeAlignmentOptions( editor.config.get( 'alignment.options' )! );
132✔
56

57
                // Filter out unsupported options and those that are redundant, e.g. `left` in LTR / `right` in RTL mode.
58
                const optionsToConvert = options.filter(
132✔
59
                        option => isSupported( option.name ) && !isDefault( option.name, locale )
518✔
60
                );
61

62
                // Once there is at least one `className` defined, we switch to alignment with classes.
63
                const shouldUseClasses = optionsToConvert.some( option => !!option.className );
367✔
64

65
                // Allow alignment attribute on all blocks.
66
                schema.extend( '$block', { allowAttributes: 'alignment' } );
132✔
67
                editor.model.schema.setAttributeProperties( 'alignment', { isFormatting: true } );
132✔
68

69
                if ( shouldUseClasses ) {
132✔
70
                        editor.conversion.attributeToAttribute( buildClassDefinition( optionsToConvert ) );
12✔
71
                } else {
72
                        // Downcast inline styles.
73
                        editor.conversion.for( 'downcast' ).attributeToAttribute( buildDowncastInlineDefinition( optionsToConvert ) );
120✔
74
                }
75

76
                const upcastInlineDefinitions = buildUpcastInlineDefinitions( optionsToConvert );
132✔
77

78
                // Always upcast from inline styles.
79
                for ( const definition of upcastInlineDefinitions ) {
132✔
80
                        editor.conversion.for( 'upcast' ).attributeToAttribute( definition );
391✔
81
                }
82

83
                const upcastCompatibilityDefinitions = buildUpcastCompatibilityDefinitions( optionsToConvert );
132✔
84

85
                // Always upcast from deprecated `align` attribute.
86
                for ( const definition of upcastCompatibilityDefinitions ) {
132✔
87
                        editor.conversion.for( 'upcast' ).attributeToAttribute( definition );
391✔
88
                }
89

90
                editor.commands.add( 'alignment', new AlignmentCommand( editor ) );
132✔
91
        }
92
}
93

94
/**
95
 * Prepare downcast conversion definition for inline alignment styling.
96
 */
97
function buildDowncastInlineDefinition( options: Array<AlignmentFormat> ) {
98
        const view: Record<string, { key: 'style'; value: { 'text-align': SupportedOption } }> = {};
120✔
99

100
        for ( const { name } of options ) {
120✔
101
                view[ name ] = {
355✔
102
                        key: 'style',
103
                        value: {
104
                                'text-align': name
105
                        }
106
                };
107
        }
108

109
        const definition = {
120✔
110
                model: {
111
                        key: 'alignment',
112
                        values: options.map( option => option.name )
355✔
113
                },
114
                view
115
        };
116

117
        return definition;
120✔
118
}
119

120
/**
121
 * Prepare upcast definitions for inline alignment styles.
122
 */
123
function buildUpcastInlineDefinitions( options: Array<AlignmentFormat> ) {
124
        const definitions = [];
132✔
125

126
        for ( const { name } of options ) {
132✔
127
                definitions.push( {
391✔
128
                        view: {
129
                                key: 'style',
130
                                value: {
131
                                        'text-align': name
132
                                }
133
                        },
134
                        model: {
135
                                key: 'alignment',
136
                                value: name
137
                        }
138
                } );
139
        }
140

141
        return definitions;
132✔
142
}
143

144
/**
145
 * Prepare upcast definitions for deprecated `align` attribute.
146
 */
147
function buildUpcastCompatibilityDefinitions( options: Array<AlignmentFormat> ) {
148
        const definitions = [];
132✔
149

150
        for ( const { name } of options ) {
132✔
151
                definitions.push( {
391✔
152
                        view: {
153
                                key: 'align',
154
                                value: name
155
                        },
156
                        model: {
157
                                key: 'alignment',
158
                                value: name
159
                        }
160
                } );
161
        }
162

163
        return definitions;
132✔
164
}
165

166
/**
167
 * Prepare conversion definitions for upcast and downcast alignment with classes.
168
 */
169
function buildClassDefinition( options: Array<AlignmentFormat> ) {
170
        const view: Record<string, AttributeDescriptor> = {};
12✔
171

172
        for ( const option of options ) {
12✔
173
                view[ option.name ] = {
36✔
174
                        key: 'class',
175
                        value: option.className!
176
                };
177
        }
178

179
        const definition = {
12✔
180
                model: {
181
                        key: 'alignment',
182
                        values: options.map( option => option.name )
36✔
183
                },
184
                view
185
        };
186

187
        return definition;
12✔
188
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc