@ckeditor/ckeditor5-source-editing 38.0.1 → 38.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,128 +1,128 @@
1
- /**
2
- * @license Copyright (c) 2003-2023, 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
- * @module source-editing/utils/formathtml
7
- */
8
- /**
9
- * A simple (and naive) HTML code formatter that returns a formatted HTML markup that can be easily
10
- * parsed by human eyes. It beautifies the HTML code by adding new lines between elements that behave like block elements
11
- * (https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements
12
- * and a few more like `tr`, `td`, and similar ones) and inserting indents for nested content.
13
- *
14
- * WARNING: This function works only on a text that does not contain any indentations or new lines.
15
- * Calling this function on the already formatted text will damage the formatting.
16
- *
17
- * @param input An HTML string to format.
18
- */
19
- export function formatHtml(input) {
20
- // A list of block-like elements around which the new lines should be inserted, and within which
21
- // the indentation of their children should be increased.
22
- // The list is partially based on https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements that contains
23
- // a full list of HTML block-level elements.
24
- // A void element is an element that cannot have any child - https://html.spec.whatwg.org/multipage/syntax.html#void-elements.
25
- // Note that <pre> element is not listed on this list to avoid breaking whitespace formatting.
26
- const elementsToFormat = [
27
- { name: 'address', isVoid: false },
28
- { name: 'article', isVoid: false },
29
- { name: 'aside', isVoid: false },
30
- { name: 'blockquote', isVoid: false },
31
- { name: 'br', isVoid: true },
32
- { name: 'details', isVoid: false },
33
- { name: 'dialog', isVoid: false },
34
- { name: 'dd', isVoid: false },
35
- { name: 'div', isVoid: false },
36
- { name: 'dl', isVoid: false },
37
- { name: 'dt', isVoid: false },
38
- { name: 'fieldset', isVoid: false },
39
- { name: 'figcaption', isVoid: false },
40
- { name: 'figure', isVoid: false },
41
- { name: 'footer', isVoid: false },
42
- { name: 'form', isVoid: false },
43
- { name: 'h1', isVoid: false },
44
- { name: 'h2', isVoid: false },
45
- { name: 'h3', isVoid: false },
46
- { name: 'h4', isVoid: false },
47
- { name: 'h5', isVoid: false },
48
- { name: 'h6', isVoid: false },
49
- { name: 'header', isVoid: false },
50
- { name: 'hgroup', isVoid: false },
51
- { name: 'hr', isVoid: true },
52
- { name: 'input', isVoid: true },
53
- { name: 'li', isVoid: false },
54
- { name: 'main', isVoid: false },
55
- { name: 'nav', isVoid: false },
56
- { name: 'ol', isVoid: false },
57
- { name: 'p', isVoid: false },
58
- { name: 'section', isVoid: false },
59
- { name: 'table', isVoid: false },
60
- { name: 'tbody', isVoid: false },
61
- { name: 'td', isVoid: false },
62
- { name: 'textarea', isVoid: false },
63
- { name: 'th', isVoid: false },
64
- { name: 'thead', isVoid: false },
65
- { name: 'tr', isVoid: false },
66
- { name: 'ul', isVoid: false }
67
- ];
68
- const elementNamesToFormat = elementsToFormat.map(element => element.name).join('|');
69
- // It is not the fastest way to format the HTML markup but the performance should be good enough.
70
- const lines = input
71
- // Add new line before and after `<tag>` and `</tag>`.
72
- // It may separate individual elements with two new lines, but this will be fixed below.
73
- .replace(new RegExp(`</?(${elementNamesToFormat})( .*?)?>`, 'g'), '\n$&\n')
74
- // Divide input string into lines, which start with either an opening tag, a closing tag, or just a text.
75
- .split('\n');
76
- let indentCount = 0;
77
- return lines
78
- .filter(line => line.length)
79
- .map(line => {
80
- if (isNonVoidOpeningTag(line, elementsToFormat)) {
81
- return indentLine(line, indentCount++);
82
- }
83
- if (isClosingTag(line, elementsToFormat)) {
84
- return indentLine(line, --indentCount);
85
- }
86
- return indentLine(line, indentCount);
87
- })
88
- .join('\n');
89
- }
90
- /**
91
- * Checks, if an argument is an opening tag of a non-void element to be formatted.
92
- *
93
- * @param line String to check.
94
- * @param elementsToFormat Elements to be formatted.
95
- */
96
- function isNonVoidOpeningTag(line, elementsToFormat) {
97
- return elementsToFormat.some(element => {
98
- if (element.isVoid) {
99
- return false;
100
- }
101
- if (!new RegExp(`<${element.name}( .*?)?>`).test(line)) {
102
- return false;
103
- }
104
- return true;
105
- });
106
- }
107
- /**
108
- * Checks, if an argument is a closing tag.
109
- *
110
- * @param line String to check.
111
- * @param elementsToFormat Elements to be formatted.
112
- */
113
- function isClosingTag(line, elementsToFormat) {
114
- return elementsToFormat.some(element => {
115
- return new RegExp(`</${element.name}>`).test(line);
116
- });
117
- }
118
- /**
119
- * Indents a line by a specified number of characters.
120
- *
121
- * @param line Line to indent.
122
- * @param indentCount Number of characters to use for indentation.
123
- * @param indentChar Indentation character(s). 4 spaces by default.
124
- */
125
- function indentLine(line, indentCount, indentChar = ' ') {
126
- // More about Math.max() here in https://github.com/ckeditor/ckeditor5/issues/10698.
127
- return `${indentChar.repeat(Math.max(0, indentCount))}${line}`;
128
- }
1
+ /**
2
+ * @license Copyright (c) 2003-2023, 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
+ * @module source-editing/utils/formathtml
7
+ */
8
+ /**
9
+ * A simple (and naive) HTML code formatter that returns a formatted HTML markup that can be easily
10
+ * parsed by human eyes. It beautifies the HTML code by adding new lines between elements that behave like block elements
11
+ * (https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements
12
+ * and a few more like `tr`, `td`, and similar ones) and inserting indents for nested content.
13
+ *
14
+ * WARNING: This function works only on a text that does not contain any indentations or new lines.
15
+ * Calling this function on the already formatted text will damage the formatting.
16
+ *
17
+ * @param input An HTML string to format.
18
+ */
19
+ export function formatHtml(input) {
20
+ // A list of block-like elements around which the new lines should be inserted, and within which
21
+ // the indentation of their children should be increased.
22
+ // The list is partially based on https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements that contains
23
+ // a full list of HTML block-level elements.
24
+ // A void element is an element that cannot have any child - https://html.spec.whatwg.org/multipage/syntax.html#void-elements.
25
+ // Note that <pre> element is not listed on this list to avoid breaking whitespace formatting.
26
+ const elementsToFormat = [
27
+ { name: 'address', isVoid: false },
28
+ { name: 'article', isVoid: false },
29
+ { name: 'aside', isVoid: false },
30
+ { name: 'blockquote', isVoid: false },
31
+ { name: 'br', isVoid: true },
32
+ { name: 'details', isVoid: false },
33
+ { name: 'dialog', isVoid: false },
34
+ { name: 'dd', isVoid: false },
35
+ { name: 'div', isVoid: false },
36
+ { name: 'dl', isVoid: false },
37
+ { name: 'dt', isVoid: false },
38
+ { name: 'fieldset', isVoid: false },
39
+ { name: 'figcaption', isVoid: false },
40
+ { name: 'figure', isVoid: false },
41
+ { name: 'footer', isVoid: false },
42
+ { name: 'form', isVoid: false },
43
+ { name: 'h1', isVoid: false },
44
+ { name: 'h2', isVoid: false },
45
+ { name: 'h3', isVoid: false },
46
+ { name: 'h4', isVoid: false },
47
+ { name: 'h5', isVoid: false },
48
+ { name: 'h6', isVoid: false },
49
+ { name: 'header', isVoid: false },
50
+ { name: 'hgroup', isVoid: false },
51
+ { name: 'hr', isVoid: true },
52
+ { name: 'input', isVoid: true },
53
+ { name: 'li', isVoid: false },
54
+ { name: 'main', isVoid: false },
55
+ { name: 'nav', isVoid: false },
56
+ { name: 'ol', isVoid: false },
57
+ { name: 'p', isVoid: false },
58
+ { name: 'section', isVoid: false },
59
+ { name: 'table', isVoid: false },
60
+ { name: 'tbody', isVoid: false },
61
+ { name: 'td', isVoid: false },
62
+ { name: 'textarea', isVoid: false },
63
+ { name: 'th', isVoid: false },
64
+ { name: 'thead', isVoid: false },
65
+ { name: 'tr', isVoid: false },
66
+ { name: 'ul', isVoid: false }
67
+ ];
68
+ const elementNamesToFormat = elementsToFormat.map(element => element.name).join('|');
69
+ // It is not the fastest way to format the HTML markup but the performance should be good enough.
70
+ const lines = input
71
+ // Add new line before and after `<tag>` and `</tag>`.
72
+ // It may separate individual elements with two new lines, but this will be fixed below.
73
+ .replace(new RegExp(`</?(${elementNamesToFormat})( .*?)?>`, 'g'), '\n$&\n')
74
+ // Divide input string into lines, which start with either an opening tag, a closing tag, or just a text.
75
+ .split('\n');
76
+ let indentCount = 0;
77
+ return lines
78
+ .filter(line => line.length)
79
+ .map(line => {
80
+ if (isNonVoidOpeningTag(line, elementsToFormat)) {
81
+ return indentLine(line, indentCount++);
82
+ }
83
+ if (isClosingTag(line, elementsToFormat)) {
84
+ return indentLine(line, --indentCount);
85
+ }
86
+ return indentLine(line, indentCount);
87
+ })
88
+ .join('\n');
89
+ }
90
+ /**
91
+ * Checks, if an argument is an opening tag of a non-void element to be formatted.
92
+ *
93
+ * @param line String to check.
94
+ * @param elementsToFormat Elements to be formatted.
95
+ */
96
+ function isNonVoidOpeningTag(line, elementsToFormat) {
97
+ return elementsToFormat.some(element => {
98
+ if (element.isVoid) {
99
+ return false;
100
+ }
101
+ if (!new RegExp(`<${element.name}( .*?)?>`).test(line)) {
102
+ return false;
103
+ }
104
+ return true;
105
+ });
106
+ }
107
+ /**
108
+ * Checks, if an argument is a closing tag.
109
+ *
110
+ * @param line String to check.
111
+ * @param elementsToFormat Elements to be formatted.
112
+ */
113
+ function isClosingTag(line, elementsToFormat) {
114
+ return elementsToFormat.some(element => {
115
+ return new RegExp(`</${element.name}>`).test(line);
116
+ });
117
+ }
118
+ /**
119
+ * Indents a line by a specified number of characters.
120
+ *
121
+ * @param line Line to indent.
122
+ * @param indentCount Number of characters to use for indentation.
123
+ * @param indentChar Indentation character(s). 4 spaces by default.
124
+ */
125
+ function indentLine(line, indentCount, indentChar = ' ') {
126
+ // More about Math.max() here in https://github.com/ckeditor/ckeditor5/issues/10698.
127
+ return `${indentChar.repeat(Math.max(0, indentCount))}${line}`;
128
+ }