biso24-editor 1.3.0 → 1.3.1

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.
Files changed (53) hide show
  1. package/CKEditor4/CHANGES.md +2182 -2182
  2. package/CKEditor4/LICENSE.md +1436 -1436
  3. package/CKEditor4/README.md +39 -39
  4. package/CKEditor4/SECURITY.md +10 -10
  5. package/CKEditor4/adapters/jquery.js +158 -158
  6. package/CKEditor4/bender-runner.config.json +16 -16
  7. package/CKEditor4/build-config.js +100 -100
  8. package/CKEditor4/ckeditor.js +30065 -30065
  9. package/CKEditor4/config.js +39 -39
  10. package/CKEditor4/contents.css +161 -161
  11. package/CKEditor4/lang/vi.js +475 -475
  12. package/CKEditor4/plugins/a11yhelp/dialogs/a11yhelp.js +143 -143
  13. package/CKEditor4/plugins/a11yhelp/dialogs/lang/vi.js +122 -122
  14. package/CKEditor4/plugins/custompaste/plugin.js +57 -57
  15. package/CKEditor4/plugins/dialog/dialogDefinition.js +4 -4
  16. package/CKEditor4/plugins/dialog/styles/dialog.css +18 -18
  17. package/CKEditor4/plugins/font/lang/vi.js +14 -14
  18. package/CKEditor4/plugins/font/plugin.js +535 -535
  19. package/CKEditor4/plugins/image2/dialogs/image2.js +558 -558
  20. package/CKEditor4/plugins/image2/lang/vi.js +21 -21
  21. package/CKEditor4/plugins/image2/plugin.js +1715 -1708
  22. package/CKEditor4/plugins/justify/plugin.js +266 -266
  23. package/CKEditor4/plugins/justify_group/plugin.js +64 -64
  24. package/CKEditor4/plugins/lineheight/LICENSE +22 -22
  25. package/CKEditor4/plugins/lineheight/README.md +2 -2
  26. package/CKEditor4/plugins/lineheight/lang/vi.js +3 -3
  27. package/CKEditor4/plugins/lineheight/plugin.js +99 -99
  28. package/CKEditor4/plugins/lineheight/readme.txt +30 -30
  29. package/CKEditor4/plugins/link/dialogs/anchor.js +82 -82
  30. package/CKEditor4/plugins/link/dialogs/link.js +777 -777
  31. package/CKEditor4/plugins/menubutton/plugin.js +99 -99
  32. package/CKEditor4/plugins/pastefromword/filter/default.js +849 -849
  33. package/CKEditor4/plugins/pastetools/filter/common.js +445 -445
  34. package/CKEditor4/plugins/pastetools/filter/image.js +163 -163
  35. package/CKEditor4/plugins/pdffile/plugin.js +36 -36
  36. package/CKEditor4/plugins/placeholder_button/plugin.js +31 -31
  37. package/CKEditor4/plugins/sourcedialog/dialogs/sourcedialog.js +88 -88
  38. package/CKEditor4/plugins/sourcedialog/lang/vi.js +9 -9
  39. package/CKEditor4/plugins/sourcedialog/plugin.js +30 -30
  40. package/CKEditor4/plugins/wordfile/plugin.js +161 -161
  41. package/CKEditor4/skins/moono-lisa/dialog.css +685 -685
  42. package/CKEditor4/skins/moono-lisa/dialog_ie.css +721 -721
  43. package/CKEditor4/skins/moono-lisa/dialog_ie8.css +746 -746
  44. package/CKEditor4/skins/moono-lisa/dialog_iequirks.css +724 -724
  45. package/CKEditor4/skins/moono-lisa/editor.css +1551 -1551
  46. package/CKEditor4/skins/moono-lisa/editor_gecko.css +1556 -1556
  47. package/CKEditor4/skins/moono-lisa/editor_ie.css +1588 -1588
  48. package/CKEditor4/skins/moono-lisa/editor_ie8.css +1639 -1639
  49. package/CKEditor4/skins/moono-lisa/editor_iequirks.css +1632 -1632
  50. package/CKEditor4/skins/moono-lisa/readme.md +46 -46
  51. package/CKEditor4/styles.js +136 -136
  52. package/CKEditor4/vendor/promise.js +385 -385
  53. package/package.json +1 -1
@@ -1,535 +1,535 @@
1
- /**
2
- * @license Copyright (c) 2003-2022, 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
- (function () {
7
- var StyleData = CKEDITOR.tools.createClass({
8
- // @param {Object} options
9
- // @param {String} options.entries Values from the configuration used to build a rich combo.
10
- // The values should be obtained from ( CKEDITOR.config#fontSize_sizes | CKEDITOR.config#font_names )
11
- // @param {String} options.styleVariable A variable name used in the style definition to build proper CKEDITOR.style.
12
- // By default it should be: ( 'size' | 'family' )
13
- // @param {Object} options.styleDefinition A template used to build each individual style definition based on entries.
14
- // The values should be obtained from ( CKEDITOR.config#fontSize_style | CKEDITOR.config#font_style )
15
- $: function (options) {
16
- var entries = options.entries.split(';');
17
-
18
- this._.data = {};
19
- this._.names = [];
20
-
21
- for (var i = 0; i < entries.length; i++) {
22
- var parts = entries[i],
23
- name,
24
- value,
25
- vars;
26
-
27
- if (parts) {
28
- parts = parts.split('/');
29
- name = parts[0];
30
- value = parts[1];
31
- vars = {};
32
-
33
- vars[options.styleVariable] = value || name;
34
-
35
- this._.data[name] = new CKEDITOR.style(options.styleDefinition, vars);
36
- this._.data[name]._.definition.name = name;
37
-
38
- this._.names.push(name);
39
- } else {
40
- entries.splice(i, 1);
41
- i--;
42
- }
43
- }
44
- },
45
-
46
- proto: {
47
- getStyle: function (name) {
48
- return this._.data[name];
49
- },
50
-
51
- addToCombo: function (combo) {
52
- for (var i = 0; i < this._.names.length; i++) {
53
- var name = this._.names[i];
54
- combo.add(name, this.getStyle(name).buildPreview(), name);
55
- }
56
- },
57
-
58
- getMatchingValue: function (editor, path) {
59
- var elements = path.elements;
60
-
61
- for (var i = 0, element, value; i < elements.length; i++) {
62
- element = elements[i];
63
-
64
- // Check if the element is removable by any of the styles.
65
- value = this._.findMatchingStyleName(editor, element);
66
-
67
- if (value) {
68
- return value;
69
- }
70
- }
71
-
72
- return null;
73
- },
74
- },
75
-
76
- _: {
77
- findMatchingStyleName: function (editor, element) {
78
- return CKEDITOR.tools.array.find(
79
- this._.names,
80
- function (name) {
81
- return this.getStyle(name).checkElementMatch(element, true, editor);
82
- },
83
- this,
84
- );
85
- },
86
- },
87
- });
88
-
89
- // @param {CKEDITOR.editor} editor
90
- // @param {Object} definition
91
- // @param {String} definition.comboName
92
- // @oaram {String} definition.commandName The name used to register the command in the editor.
93
- // @param {String} definition.styleVariable It has 'size' or 'family' as a value.
94
- // @param {Object} definition.lang A reference to the language object used for a given combo.
95
- // @param {String} definition.entries Values used for given combo options.
96
- // @param {String} definition.defaultLabel The label used to describe the default value.
97
- // @param {Object} definition.styleDefinition An object representing the defintion for a given font combo obtained
98
- // from the the configuration.
99
- // @param {Number} definition.order A value used to position the icon in the toolbar.
100
- function addCombo(editor, definition) {
101
- var config = editor.config,
102
- lang = definition.lang,
103
- defaultContentStyle = new CKEDITOR.style(definition.styleDefinition),
104
- stylesData = new StyleData({
105
- entries: definition.entries,
106
- styleVariable: definition.styleVariable,
107
- styleDefinition: definition.styleDefinition,
108
- }),
109
- command;
110
-
111
- editor.addCommand(definition.commandName, {
112
- exec: function (editor, data) {
113
- var newStyle = data.newStyle,
114
- oldStyle = data.oldStyle,
115
- range = editor.getSelection().getRanges()[0],
116
- isRemove = newStyle === undefined;
117
-
118
- if (!oldStyle && !newStyle) {
119
- return;
120
- }
121
-
122
- // If the range is collapsed we can't simply use the editor.removeStyle method
123
- // because it will remove the entire element and we want to split it instead.
124
- if (oldStyle && range.collapsed) {
125
- splitElementOnCollapsedRange({
126
- editor: editor,
127
- range: range,
128
- style: oldStyle,
129
- });
130
- }
131
-
132
- if (isRemove) {
133
- editor.removeStyle(oldStyle);
134
- } else {
135
- if (oldStyle && !isEqualStyle(oldStyle, newStyle)) {
136
- editor.removeStyle(oldStyle);
137
- }
138
-
139
- editor.applyStyle(newStyle);
140
- }
141
- },
142
-
143
- refresh: function (editor, path) {
144
- if (!defaultContentStyle.checkApplicable(path, editor, editor.activeFilter)) {
145
- this.setState(CKEDITOR.TRISTATE_DISABLED);
146
- }
147
- },
148
- });
149
-
150
- command = editor.getCommand(definition.commandName);
151
-
152
- editor.ui.addRichCombo(definition.comboName, {
153
- label: lang.label,
154
- title: lang.panelTitle,
155
- command: definition.commandName,
156
- toolbar: 'styles,' + definition.order,
157
- defaultValue: 'cke-default',
158
- allowedContent: defaultContentStyle,
159
- requiredContent: defaultContentStyle,
160
- contentTransformations:
161
- definition.styleDefinition.element === 'span'
162
- ? [
163
- [
164
- {
165
- element: 'font',
166
- check: 'span',
167
- left: function (element) {
168
- return !!element.attributes.size || !!element.attributes.align || !!element.attributes.face;
169
- },
170
- right: function (element) {
171
- var sizes = [
172
- '', // Non-existent size "0"
173
- 'x-small',
174
- 'small',
175
- 'medium',
176
- 'large',
177
- 'x-large',
178
- 'xx-large',
179
- '48px', // Closest value to what size="7" might mean.
180
- ];
181
-
182
- element.name = 'span';
183
-
184
- if (element.attributes.size) {
185
- element.styles['font-size'] = sizes[element.attributes.size];
186
- delete element.attributes.size;
187
- }
188
-
189
- if (element.attributes.align) {
190
- element.styles['text-align'] = element.attributes.align;
191
- delete element.attributes.align;
192
- }
193
-
194
- if (element.attributes.face) {
195
- element.styles['font-family'] = element.attributes.face;
196
- delete element.attributes.face;
197
- }
198
- },
199
- },
200
- ],
201
- ]
202
- : null,
203
- panel: {
204
- css: [CKEDITOR.skin.getPath('editor')].concat(config.contentsCss),
205
- multiSelect: false,
206
- attributes: { 'aria-label': lang.panelTitle },
207
- },
208
-
209
- init: function () {
210
- var defaultText = '(' + editor.lang.common.optionDefault + ')';
211
-
212
- this.startGroup(lang.panelTitle);
213
-
214
- // Add `(Default)` item as a first element on the drop-down list.
215
- this.add(this.defaultValue, defaultText, defaultText);
216
-
217
- stylesData.addToCombo(this);
218
- },
219
-
220
- onClick: onClickHandler,
221
-
222
- onRender: function () {
223
- editor.on(
224
- 'selectionChange',
225
- function (ev) {
226
- var currentValue = this.getValue(),
227
- elementPath = ev.data.path,
228
- value = stylesData.getMatchingValue(editor, elementPath);
229
-
230
- if (value) {
231
- if (value != currentValue) {
232
- this.setValue(value);
233
- }
234
-
235
- return;
236
- }
237
-
238
- // If no styles match, just empty it.
239
- this.setValue('', definition.defaultLabel);
240
- },
241
- this,
242
- );
243
-
244
- command.on(
245
- 'state',
246
- function () {
247
- this.setState(command.state);
248
- },
249
- this,
250
- );
251
- },
252
-
253
- refresh: function () {
254
- this.setState(command.state);
255
- },
256
- });
257
-
258
- function onClickHandler(newValue) {
259
- var oldValue = this.getValue();
260
-
261
- editor.focus();
262
-
263
- editor.fire('saveSnapshot');
264
-
265
- editor.execCommand(definition.commandName, {
266
- newStyle: stylesData.getStyle(newValue),
267
- oldStyle: stylesData.getStyle(oldValue),
268
- });
269
-
270
- editor.fire('saveSnapshot');
271
- }
272
- }
273
-
274
- function isEqualStyle(styleA, styleB) {
275
- if (!(styleA instanceof CKEDITOR.style) || !(styleB instanceof CKEDITOR.style)) {
276
- return false;
277
- }
278
-
279
- var hasEqualAttributes = compareAttributes(styleA, styleB),
280
- hasEqualStyles = compareStyles(styleA, styleB);
281
-
282
- return hasEqualAttributes && hasEqualStyles;
283
-
284
- function compareAttributes(styleA, styleB) {
285
- var styleAAttributes = styleA.getDefinition().attributes,
286
- styleBAttributes = styleB.getDefinition().attributes;
287
-
288
- return CKEDITOR.tools.objectCompare(styleAAttributes, styleBAttributes);
289
- }
290
-
291
- function compareStyles(styleA, styleB) {
292
- return (
293
- CKEDITOR.style.getStyleText(styleA.getDefinition()) === CKEDITOR.style.getStyleText(styleB.getDefinition())
294
- );
295
- }
296
- }
297
-
298
- // * @param {Object} options
299
- // * @param {CKEDITOR.editor} options.editor An instance of the editor.
300
- // * @param {CKEDITOR.dom.range} options.range The analyzed range.
301
- // * @param {CKEDITOR.style} options.style The old style which might already exist on this range.
302
- function splitElementOnCollapsedRange(options) {
303
- var editor = options.editor,
304
- range = options.range,
305
- style = options.style,
306
- path,
307
- matching,
308
- startBoundary,
309
- endBoundary,
310
- node,
311
- bm;
312
-
313
- path = editor.elementPath();
314
- // Find the style element.
315
- matching = path.contains(function (el) {
316
- return style.checkElementRemovable(el);
317
- });
318
-
319
- if (!matching) {
320
- return;
321
- }
322
-
323
- startBoundary = range.checkBoundaryOfElement(matching, CKEDITOR.START);
324
- endBoundary = range.checkBoundaryOfElement(matching, CKEDITOR.END);
325
-
326
- // If we are at both boundaries it means that the element is empty.
327
- // Remove it but in a way that we won't lose other empty inline elements inside it.
328
- // Example: <p>x<span style="font-size:48px"><em>[]</em></span>x</p>
329
- // Result: <p>x<em>[]</em>x</p>
330
- if (startBoundary && endBoundary) {
331
- bm = range.createBookmark();
332
- // Replace the element with its children (TODO element.replaceWithChildren).
333
- while ((node = matching.getFirst())) {
334
- node.insertBefore(matching);
335
- }
336
- matching.remove();
337
- range.moveToBookmark(bm);
338
-
339
- // If we are at the boundary of the style element, move out and copy nested styles/elements.
340
- } else if (startBoundary || endBoundary) {
341
- range.moveToPosition(matching, startBoundary ? CKEDITOR.POSITION_BEFORE_START : CKEDITOR.POSITION_AFTER_END);
342
- cloneSubtreeIntoRange(range, path.elements.slice(), matching);
343
- } else {
344
- // Split the element and clone the elements that were in the path
345
- // (between the startContainer and the matching element)
346
- // into the new place.
347
- range.splitElement(matching);
348
- range.moveToPosition(matching, CKEDITOR.POSITION_AFTER_END);
349
- cloneSubtreeIntoRange(range, path.elements.slice(), matching);
350
- }
351
-
352
- editor.getSelection().selectRanges([range]);
353
- }
354
-
355
- // Clones the subtree between `subtreeStart` (exclusive) and the
356
- // leaf (inclusive) and inserts it into the range.
357
- //
358
- // @param range
359
- // @param {CKEDITOR.dom.element[]} elements Elements path in the standard order: leaf -> root.
360
- // @param {CKEDITOR.dom.element/null} substreeStart The start of the subtree.
361
- // If null, then the leaf belongs to the subtree.
362
- function cloneSubtreeIntoRange(range, elements, subtreeStart) {
363
- var current = elements.pop();
364
- if (!current) {
365
- return;
366
- }
367
- // Rewind the elements array up to the subtreeStart and then start the real cloning.
368
- if (subtreeStart) {
369
- return cloneSubtreeIntoRange(range, elements, current.equals(subtreeStart) ? null : subtreeStart);
370
- }
371
-
372
- var clone = current.clone();
373
- range.insertNode(clone);
374
- range.moveToPosition(clone, CKEDITOR.POSITION_AFTER_START);
375
-
376
- cloneSubtreeIntoRange(range, elements);
377
- }
378
-
379
- CKEDITOR.plugins.add('font', {
380
- requires: 'richcombo',
381
- // jscs:disable maximumLineLength
382
- lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
383
- // jscs:enable maximumLineLength
384
- init: function (editor) {
385
- var config = editor.config;
386
-
387
- addCombo(editor, {
388
- comboName: 'Font',
389
- commandName: 'font',
390
- styleVariable: 'family',
391
- lang: editor.lang.font,
392
- entries: config.font_names,
393
- defaultLabel: config.font_defaultLabel,
394
- styleDefinition: config.font_style,
395
- order: 30,
396
- });
397
- addCombo(editor, {
398
- comboName: 'FontSize',
399
- commandName: 'fontSize',
400
- styleVariable: 'size',
401
- lang: editor.lang.font.fontSize,
402
- entries: config.fontSize_sizes,
403
- defaultLabel: config.fontSize_defaultLabel,
404
- styleDefinition: config.fontSize_style,
405
- order: 40,
406
- });
407
- },
408
- });
409
- })();
410
-
411
- /**
412
- * The list of font names to be displayed in the Font combo in the toolbar.
413
- * Entries are separated by semi-colons (`';'`) and it is possible to have more
414
- * than one font for each entry, in the HTML way (separated by commas).
415
- *
416
- * A display name may be optionally defined by prefixing the entries with the
417
- * name and the slash character. For example, `'Arial/Arial, Helvetica, sans-serif'`
418
- * will be displayed as `'Arial'` in the list, but will be output as
419
- * `'Arial, Helvetica, sans-serif'`.
420
- *
421
- * config.font_names =
422
- * 'Arial/Arial, Helvetica, sans-serif;' +
423
- * 'Times New Roman/Times New Roman, Times, serif;' +
424
- * 'Verdana';
425
- *
426
- * config.font_names = 'Arial;Times New Roman;Verdana';
427
- *
428
- * @cfg {String} [font_names=see source]
429
- * @member CKEDITOR.config
430
- */
431
- CKEDITOR.config.font_names =
432
- 'Arial/Arial, Helvetica, sans-serif;' +
433
- 'Comic Sans MS/Comic Sans MS, cursive;' +
434
- 'Courier New/Courier New, Courier, monospace;' +
435
- 'Georgia/Georgia, serif;' +
436
- 'Lucida Sans Unicode/Lucida Sans Unicode, Lucida Grande, sans-serif;' +
437
- 'Tahoma/Tahoma, Geneva, sans-serif;' +
438
- 'Times New Roman/Times New Roman, Times, serif;' +
439
- 'Trebuchet MS/Trebuchet MS, Helvetica, sans-serif;' +
440
- 'Verdana/Verdana, Geneva, sans-serif';
441
-
442
- /**
443
- * The text to be displayed in the Font combo if none of the available values
444
- * matches the current cursor position or text selection.
445
- *
446
- * // If the default site font is Arial, we may make it more explicit to the end user.
447
- * config.font_defaultLabel = 'Arial';
448
- *
449
- * @cfg {String} [font_defaultLabel='']
450
- * @member CKEDITOR.config
451
- */
452
- CKEDITOR.config.font_defaultLabel = '';
453
-
454
- /**
455
- * The style definition to be used to apply the font in the text.
456
- *
457
- * // This is actually the default value for it.
458
- * config.font_style = {
459
- * element: 'span',
460
- * styles: { 'font-family': '#(family)' },
461
- * overrides: [ { element: 'font', attributes: { 'face': null } } ]
462
- * };
463
- *
464
- * @cfg {Object} [font_style=see example]
465
- * @member CKEDITOR.config
466
- */
467
- CKEDITOR.config.font_style = {
468
- element: 'span',
469
- styles: { 'font-family': '#(family)' },
470
- overrides: [
471
- {
472
- element: 'font',
473
- attributes: { face: null },
474
- },
475
- ],
476
- };
477
-
478
- /**
479
- * The list of font sizes to be displayed in the Font Size combo in the
480
- * toolbar. Entries are separated by semi-colons (`';'`).
481
- *
482
- * Any kind of "CSS-like" size can be used, like `'12px'`, `'2.3em'`, `'130%'`,
483
- * `'larger'` or `'x-small'`.
484
- *
485
- * A display name may be optionally defined by prefixing the entries with the
486
- * name and the slash character. For example, `'Bigger Font/14px'` will be
487
- * displayed as `'Bigger Font'` in the list, but will be output as `'14px'`.
488
- *
489
- * config.fontSize_sizes = '16/16px;24/24px;48/48px;';
490
- *
491
- * config.fontSize_sizes = '12px;2.3em;130%;larger;x-small';
492
- *
493
- * config.fontSize_sizes = '12 Pixels/12px;Big/2.3em;30 Percent More/130%;Bigger/larger;Very Small/x-small';
494
- *
495
- * @cfg {String} [fontSize_sizes=see source]
496
- * @member CKEDITOR.config
497
- */
498
- CKEDITOR.config.fontSize_sizes =
499
- '8/8px;9/9px;10/10px;11/11px;12/12px;14/14px;16/16px;18/18px;20/20px;22/22px;24/24px;26/26px;28/28px;36/36px;48/48px;72/72px';
500
-
501
- /**
502
- * The text to be displayed in the Font Size combo if none of the available
503
- * values matches the current cursor position or text selection.
504
- *
505
- * // If the default site font size is 12px, we may make it more explicit to the end user.
506
- * config.fontSize_defaultLabel = '12px';
507
- *
508
- * @cfg {String} [fontSize_defaultLabel='']
509
- * @member CKEDITOR.config
510
- */
511
- CKEDITOR.config.fontSize_defaultLabel = '';
512
-
513
- /**
514
- * The style definition to be used to apply the font size in the text.
515
- *
516
- * // This is actually the default value for it.
517
- * config.fontSize_style = {
518
- * element: 'span',
519
- * styles: { 'font-size': '#(size)' },
520
- * overrides: [ { element: 'font', attributes: { 'size': null } } ]
521
- * };
522
- *
523
- * @cfg {Object} [fontSize_style=see example]
524
- * @member CKEDITOR.config
525
- */
526
- CKEDITOR.config.fontSize_style = {
527
- element: 'span',
528
- styles: { 'font-size': '#(size)' },
529
- overrides: [
530
- {
531
- element: 'font',
532
- attributes: { size: null },
533
- },
534
- ],
535
- };
1
+ /**
2
+ * @license Copyright (c) 2003-2022, 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
+ (function () {
7
+ var StyleData = CKEDITOR.tools.createClass({
8
+ // @param {Object} options
9
+ // @param {String} options.entries Values from the configuration used to build a rich combo.
10
+ // The values should be obtained from ( CKEDITOR.config#fontSize_sizes | CKEDITOR.config#font_names )
11
+ // @param {String} options.styleVariable A variable name used in the style definition to build proper CKEDITOR.style.
12
+ // By default it should be: ( 'size' | 'family' )
13
+ // @param {Object} options.styleDefinition A template used to build each individual style definition based on entries.
14
+ // The values should be obtained from ( CKEDITOR.config#fontSize_style | CKEDITOR.config#font_style )
15
+ $: function (options) {
16
+ var entries = options.entries.split(';');
17
+
18
+ this._.data = {};
19
+ this._.names = [];
20
+
21
+ for (var i = 0; i < entries.length; i++) {
22
+ var parts = entries[i],
23
+ name,
24
+ value,
25
+ vars;
26
+
27
+ if (parts) {
28
+ parts = parts.split('/');
29
+ name = parts[0];
30
+ value = parts[1];
31
+ vars = {};
32
+
33
+ vars[options.styleVariable] = value || name;
34
+
35
+ this._.data[name] = new CKEDITOR.style(options.styleDefinition, vars);
36
+ this._.data[name]._.definition.name = name;
37
+
38
+ this._.names.push(name);
39
+ } else {
40
+ entries.splice(i, 1);
41
+ i--;
42
+ }
43
+ }
44
+ },
45
+
46
+ proto: {
47
+ getStyle: function (name) {
48
+ return this._.data[name];
49
+ },
50
+
51
+ addToCombo: function (combo) {
52
+ for (var i = 0; i < this._.names.length; i++) {
53
+ var name = this._.names[i];
54
+ combo.add(name, this.getStyle(name).buildPreview(), name);
55
+ }
56
+ },
57
+
58
+ getMatchingValue: function (editor, path) {
59
+ var elements = path.elements;
60
+
61
+ for (var i = 0, element, value; i < elements.length; i++) {
62
+ element = elements[i];
63
+
64
+ // Check if the element is removable by any of the styles.
65
+ value = this._.findMatchingStyleName(editor, element);
66
+
67
+ if (value) {
68
+ return value;
69
+ }
70
+ }
71
+
72
+ return null;
73
+ },
74
+ },
75
+
76
+ _: {
77
+ findMatchingStyleName: function (editor, element) {
78
+ return CKEDITOR.tools.array.find(
79
+ this._.names,
80
+ function (name) {
81
+ return this.getStyle(name).checkElementMatch(element, true, editor);
82
+ },
83
+ this,
84
+ );
85
+ },
86
+ },
87
+ });
88
+
89
+ // @param {CKEDITOR.editor} editor
90
+ // @param {Object} definition
91
+ // @param {String} definition.comboName
92
+ // @oaram {String} definition.commandName The name used to register the command in the editor.
93
+ // @param {String} definition.styleVariable It has 'size' or 'family' as a value.
94
+ // @param {Object} definition.lang A reference to the language object used for a given combo.
95
+ // @param {String} definition.entries Values used for given combo options.
96
+ // @param {String} definition.defaultLabel The label used to describe the default value.
97
+ // @param {Object} definition.styleDefinition An object representing the defintion for a given font combo obtained
98
+ // from the the configuration.
99
+ // @param {Number} definition.order A value used to position the icon in the toolbar.
100
+ function addCombo(editor, definition) {
101
+ var config = editor.config,
102
+ lang = definition.lang,
103
+ defaultContentStyle = new CKEDITOR.style(definition.styleDefinition),
104
+ stylesData = new StyleData({
105
+ entries: definition.entries,
106
+ styleVariable: definition.styleVariable,
107
+ styleDefinition: definition.styleDefinition,
108
+ }),
109
+ command;
110
+
111
+ editor.addCommand(definition.commandName, {
112
+ exec: function (editor, data) {
113
+ var newStyle = data.newStyle,
114
+ oldStyle = data.oldStyle,
115
+ range = editor.getSelection().getRanges()[0],
116
+ isRemove = newStyle === undefined;
117
+
118
+ if (!oldStyle && !newStyle) {
119
+ return;
120
+ }
121
+
122
+ // If the range is collapsed we can't simply use the editor.removeStyle method
123
+ // because it will remove the entire element and we want to split it instead.
124
+ if (oldStyle && range.collapsed) {
125
+ splitElementOnCollapsedRange({
126
+ editor: editor,
127
+ range: range,
128
+ style: oldStyle,
129
+ });
130
+ }
131
+
132
+ if (isRemove) {
133
+ editor.removeStyle(oldStyle);
134
+ } else {
135
+ if (oldStyle && !isEqualStyle(oldStyle, newStyle)) {
136
+ editor.removeStyle(oldStyle);
137
+ }
138
+
139
+ editor.applyStyle(newStyle);
140
+ }
141
+ },
142
+
143
+ refresh: function (editor, path) {
144
+ if (!defaultContentStyle.checkApplicable(path, editor, editor.activeFilter)) {
145
+ this.setState(CKEDITOR.TRISTATE_DISABLED);
146
+ }
147
+ },
148
+ });
149
+
150
+ command = editor.getCommand(definition.commandName);
151
+
152
+ editor.ui.addRichCombo(definition.comboName, {
153
+ label: lang.label,
154
+ title: lang.panelTitle,
155
+ command: definition.commandName,
156
+ toolbar: 'styles,' + definition.order,
157
+ defaultValue: 'cke-default',
158
+ allowedContent: defaultContentStyle,
159
+ requiredContent: defaultContentStyle,
160
+ contentTransformations:
161
+ definition.styleDefinition.element === 'span'
162
+ ? [
163
+ [
164
+ {
165
+ element: 'font',
166
+ check: 'span',
167
+ left: function (element) {
168
+ return !!element.attributes.size || !!element.attributes.align || !!element.attributes.face;
169
+ },
170
+ right: function (element) {
171
+ var sizes = [
172
+ '', // Non-existent size "0"
173
+ 'x-small',
174
+ 'small',
175
+ 'medium',
176
+ 'large',
177
+ 'x-large',
178
+ 'xx-large',
179
+ '48px', // Closest value to what size="7" might mean.
180
+ ];
181
+
182
+ element.name = 'span';
183
+
184
+ if (element.attributes.size) {
185
+ element.styles['font-size'] = sizes[element.attributes.size];
186
+ delete element.attributes.size;
187
+ }
188
+
189
+ if (element.attributes.align) {
190
+ element.styles['text-align'] = element.attributes.align;
191
+ delete element.attributes.align;
192
+ }
193
+
194
+ if (element.attributes.face) {
195
+ element.styles['font-family'] = element.attributes.face;
196
+ delete element.attributes.face;
197
+ }
198
+ },
199
+ },
200
+ ],
201
+ ]
202
+ : null,
203
+ panel: {
204
+ css: [CKEDITOR.skin.getPath('editor')].concat(config.contentsCss),
205
+ multiSelect: false,
206
+ attributes: { 'aria-label': lang.panelTitle },
207
+ },
208
+
209
+ init: function () {
210
+ var defaultText = '(' + editor.lang.common.optionDefault + ')';
211
+
212
+ this.startGroup(lang.panelTitle);
213
+
214
+ // Add `(Default)` item as a first element on the drop-down list.
215
+ this.add(this.defaultValue, defaultText, defaultText);
216
+
217
+ stylesData.addToCombo(this);
218
+ },
219
+
220
+ onClick: onClickHandler,
221
+
222
+ onRender: function () {
223
+ editor.on(
224
+ 'selectionChange',
225
+ function (ev) {
226
+ var currentValue = this.getValue(),
227
+ elementPath = ev.data.path,
228
+ value = stylesData.getMatchingValue(editor, elementPath);
229
+
230
+ if (value) {
231
+ if (value != currentValue) {
232
+ this.setValue(value);
233
+ }
234
+
235
+ return;
236
+ }
237
+
238
+ // If no styles match, just empty it.
239
+ this.setValue('', definition.defaultLabel);
240
+ },
241
+ this,
242
+ );
243
+
244
+ command.on(
245
+ 'state',
246
+ function () {
247
+ this.setState(command.state);
248
+ },
249
+ this,
250
+ );
251
+ },
252
+
253
+ refresh: function () {
254
+ this.setState(command.state);
255
+ },
256
+ });
257
+
258
+ function onClickHandler(newValue) {
259
+ var oldValue = this.getValue();
260
+
261
+ editor.focus();
262
+
263
+ editor.fire('saveSnapshot');
264
+
265
+ editor.execCommand(definition.commandName, {
266
+ newStyle: stylesData.getStyle(newValue),
267
+ oldStyle: stylesData.getStyle(oldValue),
268
+ });
269
+
270
+ editor.fire('saveSnapshot');
271
+ }
272
+ }
273
+
274
+ function isEqualStyle(styleA, styleB) {
275
+ if (!(styleA instanceof CKEDITOR.style) || !(styleB instanceof CKEDITOR.style)) {
276
+ return false;
277
+ }
278
+
279
+ var hasEqualAttributes = compareAttributes(styleA, styleB),
280
+ hasEqualStyles = compareStyles(styleA, styleB);
281
+
282
+ return hasEqualAttributes && hasEqualStyles;
283
+
284
+ function compareAttributes(styleA, styleB) {
285
+ var styleAAttributes = styleA.getDefinition().attributes,
286
+ styleBAttributes = styleB.getDefinition().attributes;
287
+
288
+ return CKEDITOR.tools.objectCompare(styleAAttributes, styleBAttributes);
289
+ }
290
+
291
+ function compareStyles(styleA, styleB) {
292
+ return (
293
+ CKEDITOR.style.getStyleText(styleA.getDefinition()) === CKEDITOR.style.getStyleText(styleB.getDefinition())
294
+ );
295
+ }
296
+ }
297
+
298
+ // * @param {Object} options
299
+ // * @param {CKEDITOR.editor} options.editor An instance of the editor.
300
+ // * @param {CKEDITOR.dom.range} options.range The analyzed range.
301
+ // * @param {CKEDITOR.style} options.style The old style which might already exist on this range.
302
+ function splitElementOnCollapsedRange(options) {
303
+ var editor = options.editor,
304
+ range = options.range,
305
+ style = options.style,
306
+ path,
307
+ matching,
308
+ startBoundary,
309
+ endBoundary,
310
+ node,
311
+ bm;
312
+
313
+ path = editor.elementPath();
314
+ // Find the style element.
315
+ matching = path.contains(function (el) {
316
+ return style.checkElementRemovable(el);
317
+ });
318
+
319
+ if (!matching) {
320
+ return;
321
+ }
322
+
323
+ startBoundary = range.checkBoundaryOfElement(matching, CKEDITOR.START);
324
+ endBoundary = range.checkBoundaryOfElement(matching, CKEDITOR.END);
325
+
326
+ // If we are at both boundaries it means that the element is empty.
327
+ // Remove it but in a way that we won't lose other empty inline elements inside it.
328
+ // Example: <p>x<span style="font-size:48px"><em>[]</em></span>x</p>
329
+ // Result: <p>x<em>[]</em>x</p>
330
+ if (startBoundary && endBoundary) {
331
+ bm = range.createBookmark();
332
+ // Replace the element with its children (TODO element.replaceWithChildren).
333
+ while ((node = matching.getFirst())) {
334
+ node.insertBefore(matching);
335
+ }
336
+ matching.remove();
337
+ range.moveToBookmark(bm);
338
+
339
+ // If we are at the boundary of the style element, move out and copy nested styles/elements.
340
+ } else if (startBoundary || endBoundary) {
341
+ range.moveToPosition(matching, startBoundary ? CKEDITOR.POSITION_BEFORE_START : CKEDITOR.POSITION_AFTER_END);
342
+ cloneSubtreeIntoRange(range, path.elements.slice(), matching);
343
+ } else {
344
+ // Split the element and clone the elements that were in the path
345
+ // (between the startContainer and the matching element)
346
+ // into the new place.
347
+ range.splitElement(matching);
348
+ range.moveToPosition(matching, CKEDITOR.POSITION_AFTER_END);
349
+ cloneSubtreeIntoRange(range, path.elements.slice(), matching);
350
+ }
351
+
352
+ editor.getSelection().selectRanges([range]);
353
+ }
354
+
355
+ // Clones the subtree between `subtreeStart` (exclusive) and the
356
+ // leaf (inclusive) and inserts it into the range.
357
+ //
358
+ // @param range
359
+ // @param {CKEDITOR.dom.element[]} elements Elements path in the standard order: leaf -> root.
360
+ // @param {CKEDITOR.dom.element/null} substreeStart The start of the subtree.
361
+ // If null, then the leaf belongs to the subtree.
362
+ function cloneSubtreeIntoRange(range, elements, subtreeStart) {
363
+ var current = elements.pop();
364
+ if (!current) {
365
+ return;
366
+ }
367
+ // Rewind the elements array up to the subtreeStart and then start the real cloning.
368
+ if (subtreeStart) {
369
+ return cloneSubtreeIntoRange(range, elements, current.equals(subtreeStart) ? null : subtreeStart);
370
+ }
371
+
372
+ var clone = current.clone();
373
+ range.insertNode(clone);
374
+ range.moveToPosition(clone, CKEDITOR.POSITION_AFTER_START);
375
+
376
+ cloneSubtreeIntoRange(range, elements);
377
+ }
378
+
379
+ CKEDITOR.plugins.add('font', {
380
+ requires: 'richcombo',
381
+ // jscs:disable maximumLineLength
382
+ lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
383
+ // jscs:enable maximumLineLength
384
+ init: function (editor) {
385
+ var config = editor.config;
386
+
387
+ addCombo(editor, {
388
+ comboName: 'Font',
389
+ commandName: 'font',
390
+ styleVariable: 'family',
391
+ lang: editor.lang.font,
392
+ entries: config.font_names,
393
+ defaultLabel: config.font_defaultLabel,
394
+ styleDefinition: config.font_style,
395
+ order: 30,
396
+ });
397
+ addCombo(editor, {
398
+ comboName: 'FontSize',
399
+ commandName: 'fontSize',
400
+ styleVariable: 'size',
401
+ lang: editor.lang.font.fontSize,
402
+ entries: config.fontSize_sizes,
403
+ defaultLabel: config.fontSize_defaultLabel,
404
+ styleDefinition: config.fontSize_style,
405
+ order: 40,
406
+ });
407
+ },
408
+ });
409
+ })();
410
+
411
+ /**
412
+ * The list of font names to be displayed in the Font combo in the toolbar.
413
+ * Entries are separated by semi-colons (`';'`) and it is possible to have more
414
+ * than one font for each entry, in the HTML way (separated by commas).
415
+ *
416
+ * A display name may be optionally defined by prefixing the entries with the
417
+ * name and the slash character. For example, `'Arial/Arial, Helvetica, sans-serif'`
418
+ * will be displayed as `'Arial'` in the list, but will be output as
419
+ * `'Arial, Helvetica, sans-serif'`.
420
+ *
421
+ * config.font_names =
422
+ * 'Arial/Arial, Helvetica, sans-serif;' +
423
+ * 'Times New Roman/Times New Roman, Times, serif;' +
424
+ * 'Verdana';
425
+ *
426
+ * config.font_names = 'Arial;Times New Roman;Verdana';
427
+ *
428
+ * @cfg {String} [font_names=see source]
429
+ * @member CKEDITOR.config
430
+ */
431
+ CKEDITOR.config.font_names =
432
+ 'Arial/Arial, Helvetica, sans-serif;' +
433
+ 'Comic Sans MS/Comic Sans MS, cursive;' +
434
+ 'Courier New/Courier New, Courier, monospace;' +
435
+ 'Georgia/Georgia, serif;' +
436
+ 'Lucida Sans Unicode/Lucida Sans Unicode, Lucida Grande, sans-serif;' +
437
+ 'Tahoma/Tahoma, Geneva, sans-serif;' +
438
+ 'Times New Roman/Times New Roman, Times, serif;' +
439
+ 'Trebuchet MS/Trebuchet MS, Helvetica, sans-serif;' +
440
+ 'Verdana/Verdana, Geneva, sans-serif';
441
+
442
+ /**
443
+ * The text to be displayed in the Font combo if none of the available values
444
+ * matches the current cursor position or text selection.
445
+ *
446
+ * // If the default site font is Arial, we may make it more explicit to the end user.
447
+ * config.font_defaultLabel = 'Arial';
448
+ *
449
+ * @cfg {String} [font_defaultLabel='']
450
+ * @member CKEDITOR.config
451
+ */
452
+ CKEDITOR.config.font_defaultLabel = '';
453
+
454
+ /**
455
+ * The style definition to be used to apply the font in the text.
456
+ *
457
+ * // This is actually the default value for it.
458
+ * config.font_style = {
459
+ * element: 'span',
460
+ * styles: { 'font-family': '#(family)' },
461
+ * overrides: [ { element: 'font', attributes: { 'face': null } } ]
462
+ * };
463
+ *
464
+ * @cfg {Object} [font_style=see example]
465
+ * @member CKEDITOR.config
466
+ */
467
+ CKEDITOR.config.font_style = {
468
+ element: 'span',
469
+ styles: { 'font-family': '#(family)' },
470
+ overrides: [
471
+ {
472
+ element: 'font',
473
+ attributes: { face: null },
474
+ },
475
+ ],
476
+ };
477
+
478
+ /**
479
+ * The list of font sizes to be displayed in the Font Size combo in the
480
+ * toolbar. Entries are separated by semi-colons (`';'`).
481
+ *
482
+ * Any kind of "CSS-like" size can be used, like `'12px'`, `'2.3em'`, `'130%'`,
483
+ * `'larger'` or `'x-small'`.
484
+ *
485
+ * A display name may be optionally defined by prefixing the entries with the
486
+ * name and the slash character. For example, `'Bigger Font/14px'` will be
487
+ * displayed as `'Bigger Font'` in the list, but will be output as `'14px'`.
488
+ *
489
+ * config.fontSize_sizes = '16/16px;24/24px;48/48px;';
490
+ *
491
+ * config.fontSize_sizes = '12px;2.3em;130%;larger;x-small';
492
+ *
493
+ * config.fontSize_sizes = '12 Pixels/12px;Big/2.3em;30 Percent More/130%;Bigger/larger;Very Small/x-small';
494
+ *
495
+ * @cfg {String} [fontSize_sizes=see source]
496
+ * @member CKEDITOR.config
497
+ */
498
+ CKEDITOR.config.fontSize_sizes =
499
+ '8/8px;9/9px;10/10px;11/11px;12/12px;14/14px;16/16px;18/18px;20/20px;22/22px;24/24px;26/26px;28/28px;36/36px;48/48px;72/72px';
500
+
501
+ /**
502
+ * The text to be displayed in the Font Size combo if none of the available
503
+ * values matches the current cursor position or text selection.
504
+ *
505
+ * // If the default site font size is 12px, we may make it more explicit to the end user.
506
+ * config.fontSize_defaultLabel = '12px';
507
+ *
508
+ * @cfg {String} [fontSize_defaultLabel='']
509
+ * @member CKEDITOR.config
510
+ */
511
+ CKEDITOR.config.fontSize_defaultLabel = '';
512
+
513
+ /**
514
+ * The style definition to be used to apply the font size in the text.
515
+ *
516
+ * // This is actually the default value for it.
517
+ * config.fontSize_style = {
518
+ * element: 'span',
519
+ * styles: { 'font-size': '#(size)' },
520
+ * overrides: [ { element: 'font', attributes: { 'size': null } } ]
521
+ * };
522
+ *
523
+ * @cfg {Object} [fontSize_style=see example]
524
+ * @member CKEDITOR.config
525
+ */
526
+ CKEDITOR.config.fontSize_style = {
527
+ element: 'span',
528
+ styles: { 'font-size': '#(size)' },
529
+ overrides: [
530
+ {
531
+ element: 'font',
532
+ attributes: { size: null },
533
+ },
534
+ ],
535
+ };