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

ckeditor / ckeditor5 / 25927

pending completion
25927

Pull #14763

CKEditor5 code coverage

web-flow
Merge pull request #14753 from ckeditor/ck/14743-enablePlaceholder-API-should-remain-backward-compatible-for-some-time

Fix (engine): Made the `enablePlaceholder()` API to remain backward compatible for the deprecation period. It will be removed in the future. Closes #14743.
Pull Request #14763: Support for image height attribute

12436 of 12436 branches covered (100.0%)

Branch coverage included in aggregate %.

147 of 147 new or added lines in 10 files covered. (100.0%)

32669 of 32669 relevant lines covered (100.0%)

12002.96 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-2025, CKSource Holding sp. z o.o. All rights reserved.
3
 * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
4
 */
5

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

10
import { Plugin, type Editor } from 'ckeditor5/src/core.js';
11
import type { DowncastAttributeDescriptor } 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, AlignmentSupportedOption } 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 class AlignmentEditing extends Plugin {
22
        /**
23
         * @inheritDoc
24
         */
25
        public static get pluginName() {
26
                return 'AlignmentEditing' as const;
409✔
27
        }
28

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

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

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

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

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

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

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

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

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

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

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

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

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

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

90✔
94
/**
265✔
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': AlignmentSupportedOption } }> = {};
99

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

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

117
        return definition;
102✔
118
}
119

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

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

141
        return definitions;
102✔
142
}
143

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

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

163
        return definitions;
12✔
164
}
165

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

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

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

187
        return definition;
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