@ckeditor/ckeditor5-source-editing 39.0.2 → 40.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,130 +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
- // Note that <br> element is not listed and handled separately so no additional white spaces are injected.
27
- const elementsToFormat = [
28
- { name: 'address', isVoid: false },
29
- { name: 'article', isVoid: false },
30
- { name: 'aside', isVoid: false },
31
- { name: 'blockquote', isVoid: false },
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
- // Keep `<br>`s at the end of line to avoid adding additional whitespaces before `<br>`.
75
- .replace(/<br[^>]*>/g, '$&\n')
76
- // Divide input string into lines, which start with either an opening tag, a closing tag, or just a text.
77
- .split('\n');
78
- let indentCount = 0;
79
- return lines
80
- .filter(line => line.length)
81
- .map(line => {
82
- if (isNonVoidOpeningTag(line, elementsToFormat)) {
83
- return indentLine(line, indentCount++);
84
- }
85
- if (isClosingTag(line, elementsToFormat)) {
86
- return indentLine(line, --indentCount);
87
- }
88
- return indentLine(line, indentCount);
89
- })
90
- .join('\n');
91
- }
92
- /**
93
- * Checks, if an argument is an opening tag of a non-void element to be formatted.
94
- *
95
- * @param line String to check.
96
- * @param elementsToFormat Elements to be formatted.
97
- */
98
- function isNonVoidOpeningTag(line, elementsToFormat) {
99
- return elementsToFormat.some(element => {
100
- if (element.isVoid) {
101
- return false;
102
- }
103
- if (!new RegExp(`<${element.name}( .*?)?>`).test(line)) {
104
- return false;
105
- }
106
- return true;
107
- });
108
- }
109
- /**
110
- * Checks, if an argument is a closing tag.
111
- *
112
- * @param line String to check.
113
- * @param elementsToFormat Elements to be formatted.
114
- */
115
- function isClosingTag(line, elementsToFormat) {
116
- return elementsToFormat.some(element => {
117
- return new RegExp(`</${element.name}>`).test(line);
118
- });
119
- }
120
- /**
121
- * Indents a line by a specified number of characters.
122
- *
123
- * @param line Line to indent.
124
- * @param indentCount Number of characters to use for indentation.
125
- * @param indentChar Indentation character(s). 4 spaces by default.
126
- */
127
- function indentLine(line, indentCount, indentChar = ' ') {
128
- // More about Math.max() here in https://github.com/ckeditor/ckeditor5/issues/10698.
129
- return `${indentChar.repeat(Math.max(0, indentCount))}${line}`;
130
- }
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
+ // Note that <br> element is not listed and handled separately so no additional white spaces are injected.
27
+ const elementsToFormat = [
28
+ { name: 'address', isVoid: false },
29
+ { name: 'article', isVoid: false },
30
+ { name: 'aside', isVoid: false },
31
+ { name: 'blockquote', isVoid: false },
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: 'li', isVoid: false },
53
+ { name: 'main', isVoid: false },
54
+ { name: 'nav', isVoid: false },
55
+ { name: 'ol', isVoid: false },
56
+ { name: 'p', isVoid: false },
57
+ { name: 'section', isVoid: false },
58
+ { name: 'table', isVoid: false },
59
+ { name: 'tbody', isVoid: false },
60
+ { name: 'td', isVoid: false },
61
+ { name: 'th', isVoid: false },
62
+ { name: 'thead', isVoid: false },
63
+ { name: 'tr', isVoid: false },
64
+ { name: 'ul', isVoid: false }
65
+ ];
66
+ const elementNamesToFormat = elementsToFormat.map(element => element.name).join('|');
67
+ // It is not the fastest way to format the HTML markup but the performance should be good enough.
68
+ const lines = input
69
+ // Add new line before and after `<tag>` and `</tag>`.
70
+ // It may separate individual elements with two new lines, but this will be fixed below.
71
+ .replace(new RegExp(`</?(${elementNamesToFormat})( .*?)?>`, 'g'), '\n$&\n')
72
+ // Keep `<br>`s at the end of line to avoid adding additional whitespaces before `<br>`.
73
+ .replace(/<br[^>]*>/g, '$&\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
+ }